UIStackView replica for iOS 7.x and iOS 8.x

Related tags

UI TZStackView
Overview

TZStackView Carthage compatible Swift 3.0.x

A wonderful layout component called the UIStackView was introduced with iOS 9. With this component it is really easy to layout components in a row both horizontally and vertically. Apple recommends using the UIStackView wherever possible and resort to explicit NSLayoutConstraints only when there is no way to do it with UIStackView. This saves you lots of boiler plate NSLayoutConstraint creation code.

UIStackView requires iOS 9, but we're not ready to make our apps require iOS 9+ just yet. In the meanwhile, we developers are eager to try this component in our apps right now! This is why I created this replica of the UIStackView, called the TZStackView (TZ = Tom van Zummeren, my initials). I created this component very carefully, tested every single corner case and matched the results against the real UIStackView with automated XCTestCases.

Features

  • Compatible with iOS 7.x and iOS 8.x
  • Supports the complete API of UIStackView including all distribution and alignment options
  • Supports animating the hidden property of the arranged subviews
  • Supports Storyboard

So this implementation does not support Storyboard. It is meant for iOS developers who, like me, want to use the UIStackView in our existing apps and like to layout their components in code as opposed to using Storyboard.

Setup

You basically have two options to include the TZStackView in your Xcode project:

Use CocoaPods

Example Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, "8.0"
use_frameworks!

pod "TZStackView", "1.2.0"

Unfortunately, using CocoaPods with a Swift pod requires iOS 8.

Use Carthage

Example Cartfile:

github "tomvanzummeren/TZStackView" ~> 1.2.0

Run carthage to build the framework and drag the built TZStackView.framework into your Xcode project.

Drag files directly into your project

Alternatively (when you do want to support iOS 7) drag in the following classes from the Example folder directly into your Xcode project

  • TZStackView
  • TZSpacerView
  • TZStackViewAlignment
  • TZStackViewDistribution

Example usage

Given view1, view2 and view3 who have intrinsic content sizes set to 100x100, 80x80 and 60x60 respectively.

let stackView = TZStackView(arrangedSubviews: [view1, view2, view3])
stackView.distribution = .FillEqually
stackView.alignment = .Center
stackView.axis = .Vertical
stackView.spacing = 25

This would produce the following layout:

TZStackView Layout example

See the developer documentation for UIStackView for all other combinatins of distributions, alignments and axis. TZStackView works and behaves exactly the same way as the UIStackView except for not supporting Storyboard. If you do find a case where it does not behave the same way, please file a bug report.

To animate adding a view to or removing a view from the arranged subviews, simply hide or show them by adjusting the hidden property within an animation block (as described by the UIStackView reference docs as well):

UIView.animateWithDuration(0.5, animations: {
	self.view2.hidden = true
})

TZStackView hidden animation example

Migrating to UIStackView

If at a later point you decide to make iOS 9 the minimum requirement of your app (it will happen sooner or later), you will want to migrate to the real UIStackView instead of using this implementation. Because the TZStackView is a drop-in replacement for UIStackView, you simply replace:

let stackView = TZStackView(arrangedSubviews: views)

with ...

let stackView = UIStackView(arrangedSubviews: views)

... and you're good to go! You will not need to make any other changes and everything will simply work the way it worked before.

License

TZStackView is released under the MIT license. See LICENSE for details.

Comments
  • Storyboard support

    Storyboard support

    Hey,

    First of all, thanks for making this publicly available. I certainly prefer this one over OAStackView. I really don't understand why people are making a big deal about TZStackView being "redundant"... It's not redundant! It's awesome, currently is more complete (certainly appreciate the drop-in replacement) and it's all in pure swift!

    The only thing that's missing is storyboard support, but I understand that you purposely designed it to be that way.

    I was just wondering if it would be difficult or a huge task to add storyboard support? I will attempt it and even submit a PR if I manage to implement it/if you're open for PRs, but just thought I'd ask if it would require a significant amount of work? I've never really done that before so any tips would be appreciated. :)

    Thanks

    opened by jyounus 16
  • Ensure subview consistency

    Ensure subview consistency

    The UIStackView documentation specifies rules for the consistency between arranged subviews and subviews.

    In short

    • Arranged subviews is a subset of subviews so anytime a view is added to the arranged subviews it should also be added as a subview.
    • Every time a subview is removed from the stack view it should also be removed from the arranged subviews if necessary.

    Currently TZStackView does not conform to these rules. This PR aims to address that. Not all tests pass as it looks like UIStackView has changed since they were originally written (see https://github.com/tomvanzummeren/TZStackView/issues/21) but the tests I've written to verify the consistency worked when ran against beta 4

    opened by tapi 14
  • Swift 2.3/3.0 support

    Swift 2.3/3.0 support

    Just curious if this is being worked on by anyone? May be a pretty simple conversion after Xcode 8's covert tool. (I may give it a shot but I really don't know Swift 😅 )

    opened by warpling 11
  • Interface Builder

    Interface Builder

    I know your documentation says that this is not supported, but the use of Interface Builder and UIStackView are not mutually exclusive. There is no reason that I shouldn't be able to put a stack view in an Interface Builder document and use it to manage the auto layout constraints I would have had to write otherwise.

    opened by calebd 11
  • NSInternalInconsistencyException when going back in navigation

    NSInternalInconsistencyException when going back in navigation

    Hello,

    First, thanks a lot for your work !

    I'm getting this error :

    Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x7c15b6a0 of class UILabel was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x7c170270> (
    <NSKeyValueObservance 0x7c12bf90: Observer: 0x7c17a520, Key path: hidden, Options: <New: YES, Old: YES, Prior: NO> Context: 0x7c17a5b0, Property: 0x7c16fd30>
    

    I'm using TZStackView inside a custom UIView for a simple test :

            let v1 = UILabel()
            v1.backgroundColor = UIColor.greenColor()
            v1.text = "efze"
    
            let v2 = UILabel()
            v2.backgroundColor = UIColor.blueColor()
            v2.text = "efze"
    
            let v3 = UILabel()
            v3.backgroundColor = UIColor.yellowColor()
            v3.text = "efze"
    
            container = TZStackView(arrangedSubviews: [
                v1,v2,v3
                ])
    
            container.setTranslatesAutoresizingMaskIntoConstraints(false)
            container.backgroundColor = UIColor.purpleColor()
            container.axis = .Vertical
            container.distribution = .FillEqually
            container.alignment = TZStackViewAlignment.Fill
            container.spacing = 15
    
    
            self.addSubview(container)
    
    

    This UIView is displayed when the user selects an item in a collectionView (via a NavigationController) and the UIView with the TZStackView is correctly displayed. The error happens when the user click the back button.

    Did I do something wrong ? I saw a similar issue (#7) but I'm using 1.0.3 and it is still happening.

    Thanks for your help !

    opened by YeFFreY 11
  • UIViewAlertForUnsatisfiableConstraints error while hiding a view

    UIViewAlertForUnsatisfiableConstraints error while hiding a view

    I have a UIView that contains few buttons. They are all separated from each other with 8 points space. The buttons have no height constraints.

    This view is then added to your stackview and the axis is set to vertical. When I hide the view, it actually set a constraint saying the view should have a height of 0. Then I get an UIViewAlertForUnsatisfiableConstraints error because I have some fixed constraints (8 points gaps) in my view.

    What's my solution to avoid those errors?

    Thanks.

    opened by nico75005 8
  • TZStackView 1.1.0 doesn't compile under Xcode 6.4

    TZStackView 1.1.0 doesn't compile under Xcode 6.4

    I'm assuming this is because you changed the codebase to be Swift 2.0. This seems a little pre-emptive as Xcode 7 is still pre-release.

    Great project btw, can't wait to use it.

    Tristan

    opened by Codeglee 8
  • Added shared framework target to support Carthage.

    Added shared framework target to support Carthage.

    Follow-up for issue #19.

    Carthage needs to find the xcodeproj and a shared framework target. As such it is impedimental to have multiple xcodeproj files and subprojects, especially when the xcodeproj file has a different name than the Project and no shared framework.

    opened by regexident 8
  • Unexpected behaviour with UILabel.numberOfLines = 0

    Unexpected behaviour with UILabel.numberOfLines = 0

    I have a TZStackView hierarchy with a bunch of UILabels in it. They have numberOfLines = 0. The problem is that if I attempt the same code with UIStackView on iOS 9, or TZStackView on iOS 9, the UILabels wrap. However with TZStackView on iOS 8.x, the UILabel is ellipsized. Any thoughts on this?

    opened by Mackarous 7
  • Disable backgroundColor

    Disable backgroundColor

    Overrides the backgroundColor property inherited from UIView to be disabled.

    This is in order to mimic an actual UIStackView, which is a non-drawing view, and protect users of TZStackView from becoming reliant on setting a TZStackView's background color. This should be one less surprise for users when they eventually migrate from TZStackView to UIStackView in the future.

    opened by rzulkoski 5
  • first pass implementation of problem in #20

    first pass implementation of problem in #20

    This PR represents one possible way to implement Interface Builder support for TZStackView. The strategy taken here was:

    1. Make all the necessary parameters configurable through IBInspectable. This is relatively inoffensive (aside from being delicate because Xcode can't have enumerated types as IBInspectable) and makes for a nice addition.
    2. At design time, insert nonsense subviews into the hierarchy to preview the behavior of the stack view. At run time, convert any subviews into arrangedSubviews. This is a bit more controversial.

    Ultimately, I think this code as it stands is not production ready. However, I think it's a good starting point to discuss how to implement this feature.

    opened by pauljonescodes 5
  • Crash on deinit `UIView was deallocated while key value observers were still registered with it`

    Crash on deinit `UIView was deallocated while key value observers were still registered with it`

    I have a crash:

    Fatal Exception: NSInternalInconsistencyException
    An instance 0x151eabd0 of class UIView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x151b6c10> ( <NSKeyValueObservance 0x14384cd0: Observer: 0x151b0090, Key path: hidden, Options: <New: YES, Old: YES, Prior: NO> Context: 0x151b0180, Property: 0x8814fc0> )
    

    In my view I have this code:

    deinit {
        stackView.arrangedSubviews.forEach { view in
          stackView.removeArrangedSubview(view)
        }
      }
    

    After investigation I found that method removeArrangedSubview does not call removeHiddenListener. Why?

    You are removing listeners by code:

    deinit {
            // This removes `hidden` value KVO observers using didSet()
            { self.arrangedSubviews = [] }()
        }
    

    But arrangedSubviews are already empty. Why don't you remove listeners for all listeners in registeredKvoSubviews array?

    opened by NickSuglobov 0
  • Updated to Swift 4

    Updated to Swift 4

    Here's a quick pass of the Swift 4 conversion we're using in a project. Unfortunately some 'vertical' tests fail. firstAttribute and secondAttribute are traling instead of leading.

    opened by helkarli 1
  • Make TZStackView open to allow subclassing

    Make TZStackView open to allow subclassing

    TZStackView cannot be subclassed in Swift 3, since the class is public instead of open.

    We have to add some additional functionality to this class, so it would be great if you could make this class open. Thanks!

    opened by danielsaidi 0
Releases(1.3.0)
Owner
Tom van Zummeren
Tom van Zummeren
DesafioMobile2You - This project consists of creating a replica of a TodoMovies screen

DesafioMobile2You Swift IOS Este projeto consiste na criação da réplica de uma t

Leonardo P M 0 Feb 3, 2022
A controller that uses a UIStackView and view controller composition to display content in a list

StackViewController Overview StackViewController is a Swift framework that simplifies the process of building forms and other static content using UIS

Seed 867 Dec 27, 2022
Porting UIStackView to iOS 7+

OAStackView iOS 9 introduced the very cool UIStackView, UIStackView can be used to easily create simple and complex layouts. As expected UIStackView c

Omar Abdelhafith 2.2k Dec 3, 2022
A micro UIStackView convenience API inspired by SwiftUI

Stacks A micro UIStackView convenience API inspired by SwiftUI. let stack: UIView = .hStack(alignment: .center, margins: .all(16), [ .vStack(spaci

Alexander Grebenyuk 74 Jul 27, 2022
An alternative to UIStackView for common Auto Layout patterns.

StackLayout StackLayout builds on Auto Layout to make some of the most common layouts easier to manage. It creates the constraints that you need and a

Bridger Maxwell 76 Jun 29, 2022
Fetch the star wars api from all the planets and list and show details using Swift UI and Combine

Star Wars Planets Fetch the star wars planet data by using stat war api, list and show details using SwiftUI and Combine frameworks ?? Swift UI Framew

null 1 Aug 10, 2022
A custom stretchable header view for UIScrollView or any its subclasses with UIActivityIndicatorView and iPhone X safe area support for content reloading. Built for iOS 10 and later.

Arale A custom stretchable header view for UIScrollView or any its subclasses with UIActivityIndicatorView support for reloading your content. Built f

Putra Z. 43 Feb 4, 2022
🏞 A simple iOS photo and video browser with optional grid view, captions and selections written in Swift5.0

Introduction ?? MediaBrowser can display one or more images or videos by providing either UIImage objects, PHAsset objects, or URLs to library assets,

Kyle Yi 631 Dec 29, 2022
MZFormSheetPresentationController provides an alternative to the native iOS UIModalPresentationFormSheet, adding support for iPhone and additional opportunities to setup UIPresentationController size and feel form sheet.

MZFormSheetPresentationController MZFormSheetPresentationController provides an alternative to the native iOS UIModalPresentationFormSheet, adding sup

Michał Zaborowski 979 Nov 17, 2022
UIPheonix is a super easy, flexible, dynamic and highly scalable UI framework + concept for building reusable component/control-driven apps for macOS, iOS and tvOS

UIPheonix is a super easy, flexible, dynamic and highly scalable UI framework + concept for building reusable component/control-driven apps for macOS, iOS and tvOS

Mohsan Khan 29 Sep 9, 2022
Step-by-step progress view with labels and shapes. A good replacement for UIActivityIndicatorView and UIProgressView.

StepProgressView Step-by-step progress view with labels and shapes. A good replacement for UIActivityIndicatorView and UIProgressView. Usage let progr

Yonat Sharon 340 Dec 16, 2022
High performance and lightweight UIView, UIImage, UIImageView, UIlabel, UIButton, Promise and more.

SwiftyUI High performance and lightweight UIView, UIImage, UIImageView, UIlabel, UIButton and more. Features SwiftyView GPU rendering Image and Color

Haoking 336 Nov 26, 2022
BulletinBoard is an iOS library that generates and manages contextual cards displayed at the bottom of the screen

BulletinBoard is an iOS library that generates and manages contextual cards displayed at the bottom of the screen. It is especially well

Alexis (Aubry) Akers 5.3k Jan 2, 2023
⚡️ A library of widgets and helpers to build instant-search applications on iOS.

By Algolia. InstantSearch family: InstantSearch iOS | InstantSearch Android | React InstantSearch | InstantSearch.js | Angular InstantSearch | Vue Ins

Algolia 567 Dec 20, 2022
Modular and customizable Material Design UI components for iOS

Material Components for iOS Material Components for iOS (MDC-iOS) helps developers execute Material Design. Developed by a core team of engineers and

Material Components 4.6k Dec 29, 2022
📝 The next in the generations of 'growing textviews' optimized for iOS 8 and above.

NextGrowingTextView The next in the generations of 'growing textviews' optimized for iOS 8 and above. As a successor to HPGrowingTextView, NextGrowing

Muukii 1.7k Jan 7, 2023
Progress and Activity Indicators for iOS apps

Progress Indicators and Activity Views for iOS Apps Features Storyboard compatible, configure apprearance with the property inspector. fully animated,

Alexander Kasimir 101 Nov 13, 2022
StarryStars is iOS GUI library for displaying and editing ratings

StarryStars StarryStars is iOS GUI library for displaying and editing ratings Features StarryStars' RatingView is both IBDesignable and IBInspectable

Peter Prokop 175 Nov 19, 2022
Simple and highly customizable iOS tag list view, in Swift.

TagListView Simple and highly customizable iOS tag list view, in Swift. Supports Storyboard, Auto Layout, and @IBDesignable. Usage The most convenient

Ela Workshop 2.5k Jan 5, 2023