UIStackView Tutorial for iOS: Introducing Stack Views

Learn how to simplify your iOS layouts with UIStackView. Layout a series of views horizontally or vertically, using alignment, distribution and spacing. By Ehab Amer.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Stack View Appearance

The property that determines how a stack view lays out its subviews along its axis is distribution. Currently, it’s set to Fill, which means the subviews will completely fill the stack view along its axis. To accomplish this, the stack view will only expand one of its subviews to fill that extra space. Specifically, it expands the view with the lowest horizontal content hugging priority, or if all of the priorities are equal, it expands the first view.

However, you don’t want the buttons to fill the stack view completely — you want them to be equally spaced.

Make sure the stack view is still selected and go to the Attributes inspector. Change the Distribution from Fill to Equal Spacing:

Now build and run, tap on any cell, and rotate the simulator. You’ll see that the bottom buttons now space themselves equally!

When implementing a UI, always ask yourself whether the elements fit the available space.

Here’s an example of how your content can affect the user’s experience: Change the title of the Wikipedia button to Wikipedia website and run the app. Rotate the simulator from portrait to landscape to see the difference.

In the portrait orientation where the space is tighter, the text in the last button is clipped, while in the landscape everything fits well.

This is something that you’ll come across frequently, especially with narrower screen sizes like the iPhone SE.

Fortunately, it’s an easy fix. With the stack view still selected, go back to Attributes inspector. Change Distribution from Equal Spacing to Fill Proportionally and change the spacing value to 10:

Now, build and run and check both orientations. You’ll find everything in order.

Change the name of the button back to Wikipedia.

Congratulations, you’ve built your first stack view!

Without a Stack View

In order to solve this spacing problem without a stack view, you would have to use one spacer view between each pair of buttons, adding equal width constraints to all of the spacer views, as well as several additional constraints to position the spacer views correctly.

This would look something like the following. For visibility in the screenshot, the spacer views display a light gray background:

uistackview tutorial

It isn’t too problematic if you have to do this once in the storyboard, but many views are dynamic. It’s not a straightforward task to add a new button or to hide or remove an existing button at runtime because of the adjacent spacer views and constraints.

In order to hide a view within a stack view, set the contained view’s hidden property to true, and the stack view handles the rest. This is how you’ll fix the spacing under the WEATHER label when the user hides the text below it. You’ll do that in this tutorial once you’ve added the weather section labels into a stack view.

Note: You now know how to specify the spacing between subviews in your stack. But what if you want different spacing after a specific subview? Starting from iOS 11, you can do that using setCustomSpacing:afterView.

Converting the Sections

Next, you’ll convert all of the other sections in SpotInfoViewController to use stack views as well. This enables you to complete the remaining tasks. Begin with the rating section.

Converting the Rating Section

Above the stack view you created, select the RATING label and the stars label next to it.

Then, click Editor ▸ Embed in ▸ Stack View.

Now, select the newly created stack view and click the Add New Constraints button again. Place a checkmark in Constrain to margins and add the following three constraints:

Top: 20, Leading: 0, Bottom: 20

Now go to the Attributes inspector and set the spacing to 8.

Note: You may have noticed that the spacing is already set to 8. Previously, the spacing was set automatically to 24. Xcode has become smart enough to infer the spacing value to match what it was before embedding the views. Pretty cool, right?

Build and run to verify that everything looks the same as before.

Un-embedding a Stack View

Before you go too far, it’s good to have some first aid training for when things go wrong. For example, you may find yourself with an extra stack view, perhaps because of experimentation, refactoring or by accident.

Fortunately, there’s an easy way to unembed views from a stack view.

First, select the stack view you want to remove. Click the Embed In button. Next, select Unembed on the context menu that appears:

Another way to do this is to select the stack view and choose Editor ▸ Unembed from the menu.

Creating a Vertical Stack View

Now, create your first vertical stack view. Select the WHY VISIT label and <whyVisitLabel> below it, and then select Embed in ▸ Stack View.

When you embed the labels in a stack view, Xcode infers that it should be a vertical stack based on the position of the labels.

The lower label previously had a constraint pinning it to the right margin, but embedding the label in the stack view removed that constraint. Currently, the stack view has no constraints, so it adopts the intrinsic width of its largest view.

With the stack view selected, click the Add New Constraints button. Set the Top, Leading and Trailing constraints to 0. Again, make sure to check Constrain to margins.

Then, click the dropdown to the right of the bottom constraint and select WEATHER (current distance = 20):

By default, Interface Builder shows you the constraints to the nearest neighbor, which for the bottom constraint is the Hide button at a distance of 15. You need the constraint to be to the WEATHER label below it.

Finally, click Add 4 Constraints. You should now see the following:

Now you have an expanded stack view with right edges pinned to the right margin of the view. However, the bottom label is still the same width. You’ll fix this by updating the stack view’s alignment property.

Alignment Property

The alignment property determines how a stack view lays out its views perpendicular to its axis. For a vertical stack view, the possible values are Fill, Leading, Center, and Trailing.

The possible alignment values for a horizontal stack view differ slightly:

uistackview tutorial

The horizontal stack view has .top instead of .leading and has .bottom instead of .trailing. There are also two more properties that are valid only in the horizontal direction, .firstBaseline and .lastBaseline.

Select each value to see how it affects label placement in the vertical stack view:

Fill:

uistackview tutorial

Leading:

uistackview tutorial

Center:
uistackview tutorial

Trailing:

uistackview tutorial

When you’re done testing each value, set the Alignment to Fill:

uistackview tutorial

Build and run to verify that everything looks good and that there are no regressions.

Specifying Fill means you want all the views to fill the stack view perpendicular to its axis. This causes the WHY VISIT label to expand to the right edge as well.

What if you only wanted the bottom label to expand to the edge?

For now, it doesn’t matter since both labels will have a clear background at runtime, but it will matter when you’re converting the weather section.

You’ll learn how to accomplish that with the use of an additional stack view.