UIStackView Demystified

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 UILabels of varying sizes and colors. The spacing has been set to 10.0.

UIStackView horizontal fill example

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 to arrangedSubviews and subviews.

  • removeArrangedSubview() only removes the view from arrangedSubviews and it will remain in subviews

  • addSubview() only adds the view to subviews and it will not be included in the layout process

  • When calling removeFromSuperview on a subview, it will be removed from both arrangedSubviews and subviews

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

UIStackView distribution .Fill contentHuggingPriority example

.FillEqually

Resizes each item equally along the axis to fill the available space. Also takes into account spacing between items.

UIStackView distribution .FillEqually example

.FillProportionally

Resizes each item by proportionally distributing the extra space based on their intrinsicContentSize along the axis.

UIStackView horizontal .FillProportionally example

.EqualSpacing

Sizes each item based on its intrinsicContentSize and spaces them all equally along the axis. Uses spacing as a minimum value.

UIStackView distribution .EqualSpacing example

.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.

UIStackView .EqualCentering example

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.

UIStackView alignment .Fill example

.Leading / .Top

Pins each item to the top or leading edge.

Use .Leading when axis is .Vertical and .Top when axis is .Horizontal

UIStackView alignment .Leading example

.Center

Centers each item.

UIStackView alignment .Center example

.Trailing / .Bottom

Pins each item to the bottom or trailing edge.

Use .Trailing when axis is .Vertical and .Bottom when axis is .Horizontal

UIStackView alignment .Trailing example

.FirstBaseline

Aligns the first line’s baseline of each item. Only usable when axis is .Horizontal.

UIStackView alignment .FirstBaseline example

.LastBaseline

Aligns the last line’s baseline of each item. Only usable when axis is .Horizontal.

UIStackview alignment .LastBaseline example

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.

UIStackview spacing example

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:

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, UIStackViews 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 UIStackViews are then contained in a parent UIStackView denoted on the left.

UIStackview nesting example

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


Do you have a project in mind? We’d love to work with you. If you’d like an opportunity to work on projects with us, check out our Careers page. We’re hiring!

3 thoughts on “UIStackView Demystified”

  1. Thank you for writing this up! It’s exactly what I’ve been looking for.

  2. Great article and example!

  3. 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.

Leave a Comment