UIStackView
was released to the public with iOS 9. It is a container view that internally handles layout of its subviews. The layout can be configured by changing its properties axis
, distribution
, alignment
, and spacing
. It lets you remove tedious NSLayoutConstraint
setup code.
Below is a very simple implementation of a UIStackView
that contains 4 UILabel
s of varying sizes and colors. The spacing
has been set to 10.0
.
arrangedSubviews
UIStackView
contains a property arrangedSubviews
which is a subset of subviews
. Only views in this subset will be laid out by the UIStackView
. Subviews that are not arranged subviews can be used to visually style the stack view (see Non-Rendering below). Ordering in this subset also does not affect the ordering of views in subviews
. In the example, each UILabel
is added to arrangedSubviews
.
addArrangedSubview()
adds the view toarrangedSubviews
andsubviews
.removeArrangedSubview()
only removes the view fromarrangedSubviews
and it will remain insubviews
addSubview()
only adds the view tosubviews
and it will not be included in the layout process- When calling
removeFromSuperview
on a subview, it will be removed from botharrangedSubviews
andsubviews
axis
A UILayoutConstraintAxis
enum:
.Horizontal
Lays out arrangedSubviews
horizontally in a row
.Vertical
Lays out arrangedSubviews
vertically in a column
distribution
A UIStackViewDistribution
enum:
.Fill
Attempts to fill the space along the axis
with the items. It sizes each item via its intrinsicContentSize
and if there is a leftover or a lack of space, it uses each item’s contentCompressionResistancePriority
and contentHuggingPriority
to determine which items to grow or shrink. Also takes into account spacing
between items.
contentCompressionResistancePriority
– The view with the lowest value gets truncated when there is not enough space to fit everything’s intrinsicContentSize
contentHuggingPriority
– The view with the lowest value gets expanded beyond its intrinsicContentSize
when there is leftover space to fill
In the example below, the red label has the lowest contentHuggingPriority
.FillEqually
Resizes each item equally along the axis
to fill the available space. Also takes into account spacing
between items.
.FillProportionally
Resizes each item by proportionally distributing the extra space based on their intrinsicContentSize
along the axis
.
.EqualSpacing
Sizes each item based on its intrinsicContentSize
and spaces them all equally along the axis
. Uses spacing
as a minimum value.
.EqualCentering
Sizes each item based on its intrinsicContentSize
and spaces them all equally from each others center along the axis
. Uses spacing
as a minimum value.
alignment
A UIStackViewAlignment
enum, the alignment
property refers to the alignment of items perpendicular to the axis
.
Ex: axis
is .Horizontal
, so alignment
specifies the how the items are aligned vertically
.Fill
Resizes each item by filling the available space.
.Leading
/ .Top
Pins each item to the top or leading edge.
Use .Leading
when axis
is .Vertical
and .Top
when axis
is .Horizontal
.Center
Centers each item.
.Trailing
/ .Bottom
Pins each item to the bottom or trailing edge.
Use .Trailing
when axis
is .Vertical
and .Bottom
when axis
is .Horizontal
.FirstBaseline
Aligns the first line’s baseline of each item. Only usable when axis
is .Horizontal
.
.LastBaseline
Aligns the last line’s baseline of each item. Only usable when axis
is .Horizontal
.
Spacing
spacing
determines the amount of space between arrangedSubviews
along the axis
when the distribution
is set to any of the fill values (described above). When the distribution
is set to either of the equal values, spacing
determines the minimum amount of space between arrangedSubviews
along the axis
.
In the example below, spacing
is set to 10.0
.
Non-Rendering
UIStackView
is a non-rendering element, and such does not get drawn on the screen. This means that backgroundColor
, layer
borders, and any other visual tweaks available to UIView
essentially does nothing. If you want to add any of these things, just add a UIView
to it as a subview
like below:
let borderView = UIView(frame: CGRect.zero) borderView.translatesAutoresizingMaskIntoConstraints = false borderView.layer.borderColor = UIColor.blackColor().CGColor borderView.layer.borderWidth = 2.0 stackView.addSubview(borderView) let borderViewConstraints: [NSLayoutConstraint] = [ borderView.topAnchor.constraintEqualToAnchor(stackView.topAnchor), borderView.leadingAnchor.constraintEqualToAnchor(stackView.leadingAnchor), borderView.trailingAnchor.constraintEqualToAnchor(stackView.trailingAnchor), borderView.bottomAnchor.constraintEqualToAnchor(stackView.bottomAnchor), ] NSLayoutConstraint.activateConstraints(borderViewConstraints)
Hiding Arranged Subviews
Setting an arrangedSubview
‘s hidden
property to true
will cause UIStackView
to internally apply a width and height NSLayoutConstraint
of zero and ignore it when spacing out items.
Nesting
If you run into situations where multiple elements need to be arranged along multiple axes, UIStackView
s can be nested inside each other. Below is the layout from the example project. Each property UILabel
and UISegmentedControl
are contained in a UIStackView
. All of the UIStackView
s are then contained in a parent UIStackView
denoted on the left.
Summary
Overall, UIStackView
is a much needed addition to UIKit
that helps developers quickly and easily create responsive UIs. It eliminates tedious layout code and forces you to think about how elements will be resized when their containers change size.
Example Project
An example project for iPad is available at Github
Thank you for writing this up! It’s exactly what I’ve been looking for.
Great article and example!
Since UIStackView does not render its background color, how would you arrange for it to draw a color fill underneath its arranged subviews? The only idea that might work is adding the stack view as a subview to another view (parent), and constraining the parent’s size to the stack view’s size. Cumbersome to say the least.