This component is one of the things that should´ve been there for ages, as it facilitates layout design considerably. In every UI environment there is a basic need to stack elements horizontally or vertically, having them rearranged when any element is added or removed. This takes a second in other platforms however iOS auto-layout is some times a painful process for pretty simple tasks.
What´s wrong with the good old, super awesome AutoLayout?
Consider the following layout (“–” represents padding):
Doing this silly layout the “old” way involves lots of constraints, for instance:
- align the views vertically (2 or 3 constraints)
- set leading and trailing of each view (3 to 4 constraints)
- set with and height of each view (6 constraints or maybe 3 if they provide instrinsic height)
Next week your boss comes to tell you that view2 is no longer needed, so you have to:
- delete view2
- manually rearrange view3 to get the place where view2 was placed, fixing all the wrong constraints
Then, a great designer in your team tells you by slack that paddings are too small. There´s no single “padding” or “margin” property. Again, you need to change all leading/trailing constraints of each view, one by one.
And well… we are talking about “design time” here (aka Interface Builder). If you need to do this on runtime (state changes) it may become a nightmare because you first need to locate the attached constraints to remove them and then create new ones, if you know what I mean.
Now imagine you´ve got like 5 more places in the screen where this can happen. Next move is probably pulling your hair and complain about how misserable your life is.
What can UIStackView do for me?
This guy is using AutoLayout internally and it does nothing you can´t do with AutoLayout and some code but it will make your life easier in many ways. Think of it as some kind of Android LinearLayout. It can also be nested easily to achieve more complex layouts.
Going back to the previous example, if view1, view2 and view3 were within a
UIViewStack they wouldn´t need any constraint created manually (unless you want to) and removing one of them (design time or runtime) will readjust all the constraints for you. Done. Same happens if you want to add a new view to the stack. You can even animate that change with a one liner, as we will see later.
- Design time layouts become easier
- Coded layouts become easier
- Runtime state changes (adding or removing elements) take a single line of code.
- Animating layout changes is now very simple
Shut up and show me the code
No need to give you all the small details of this component, as you can easily google it. Instead, I´m going to jump right to the code with some real cases I came up with.
All the samples will be coded (sorry IB fans) and layout with the anchor constraint API (did I say it correctly?) and a few method extensions to speed up trival tasks. If you don´t know what it is, go ahead and read my previous post.
Adding and removing elements
UIStackView to manage children constraints propertly, use any of the following methods:
You can also remove a child view like you normally would:
A vertical scroll of stacked elements
Let´s say you need a simple scroll for a small number of stacked elements (better use a Table if you need many) but you don´t need/want to mess with cells.
UIStackView within a
UIScrollView will make the trick:
I´m using here two custom method extensions: FullSizeOf() and EnableAutoLayout to make the code cleaner.
Nesting stacks is no mistery as it works like nesting any other view.
The layout hierarchy looks like the following:
UIScrollView UIStackView UIView (with gray background) UILabel UIStackView Children UIView (with gray background) UILabel UIStackView Children ...
Grab the source code for this screen here
Add/remove elements with animation
Animating constraints in iOS has been always simple:
UIViewStack is not different. When adding or removing a view from the stack it will internally change the constraints with AutoLayout so the animation works in the same way. Let´s create a button that will add an arranged subview with a random color to the stack. Then destroy that view when user taps on it:
Accordion component POC
In a real application I would probably use a
UITableView to create an accordion component because it will handle items and scroll more efficiently using cell virtualization. However this can be done faster with a
UIStackView and it works pretty decently for a few views:
In this sample, only a single item can be opened at a time. The content view is actually a resized
UILabel with a random height, but it could be anything else.
It´s worth saying that content views in this sample are all added on initialization and later hidden and shown. This means that
UIStackView is smart enough to handle constraint changes not only when views are added or removed, but also when their visibility changes (
view.Hidden = true|false), simplifying your code even more.
Change axis with animation
I don´t see any useful case to change the axis in a real app, but here it is. Changing from horizontal to vertical and viceversa takes one line:
And if you want to animate it:
Enough for now, you can find these and other samples in the github repo.
Here it´s a screen recording with the rest of them:
UIStackView is available from iOS 9. If you need to support previous versions, go ahead and try Cheesebaron TZStackView.