4 Comments

Fill and Space Content Evenly in a UIStackView

I had a great suggestion for my next topic on UIStackViews from my previous blog post. Dan asked, “Could you show us how you would put four fields on the same row evenly?”

UITextFields present an interesting problem for UIStackViews because they do not have an intrinsic content size. They shrink to fit the text that is inside them or get really tiny if they have no text. You have to tell the stack view how to stretch the controls inside it, and in this case, also stretch them evenly across the row. The example we are going to build will look like this:

A screenshot of an iPhone screen displaying final fields with spacing created in UIStackView

Laying Out the Controls

You have a couple of ways to get started. As with any container view in iOS, you can place the controls on your storyboard scene first and then encapsulate them in a container, or place the container on the scene first and drag controls into the container.

I will start with the former method, dragging four UITextFields onto my storyboard scene and encapsulating them in a stack view.
A screenshot of a user adding fields to stack view
Hit the Stack button to encapsulate your selected controls in a stack view.
A screenshot of a user hitting the Stack button in UIStackView

Because the UITextFields do not have an intrinsic content size, the fields shrink and are grouped in a tight bundle of four within the new stack view.
A screenshot of shrunk fields grouped in a tight bundle of four within the new stack view.

Now constrain the UIStackView in the parent view using Auto Layout. I added constraints on the leading, trailing, and top of the stack view to the parent view.
A screenshot of the Add New Constraints menu in UIStackView

Finally, you should have four text fields in a stack view constrained to the parent view. Now we will take a look at how to space them out equally.
A screenshot of four text fields in a stack view constrained to the parent view.

Configuring the UIStackView

Now that we have our controls in the stack view, we need to tell it how to distribute the controls. As you can see, it defaults to fill the stack view, but it doesn’t automatically do it equally.

Set the distribution on the stack view to Fill Equally.
A screenshot of setting alignment to "top" and distribution to "fill" in Stack ViewA screenshot of a user setting "Distribution" to "Fill Equally" in Stack View

The result of filling equally is almost what we want. We have the text fields filling out the stack view equally, but they are a little too close to each other.
A screenshot of text fields filled equally with no spacing in UIStackView

In the “old” days before UIStackViews, when you wanted spacing in between your controls, you had to add Auto Layout constraints between them. Now with stack views, we can configure the amount of space between each control.

A screenshot of a user adding space between text fields in Stack View

Now we have the exact look that we want.
A screenshot of the final fields with spacing in Stack View

Fixing Auto Layout Warnings

It may happen that you get Auto Layout warnings when you try my example. I believe the root cause is iOS’s inability to do sub-pixel rendering. What I mean by that is you can’t say a control is 4.5 pixels wide–it has to be a whole number. I usually encounter this when I have a number of controls that I want to space equally across a view. Depending on how wide my view is and how many controls I am spacing out, the result may not divide into equal whole number pixels. Xcode will report this as an Auto Layout warning that is difficult to get rid of.

Here are the warnings that I get on Xcode 7.3.
A screenshot of Auto Layout warning in StackView Screenshot of an auto layout warning detail in StackView

When I right-click on the yellow triangle, updating the frames does not fix the problem. It seems like there is nothing that will make Xcode happy. To make the warning go away, you can click on just one of your text fields in the stack view and set the Content Hugging Priority to be one less than the rest of the controls in the stack view. In my case the default is 250, so I set one of the text fields to be 249. Problem fixed!

A screenshot of a user adding content hugging priorities to the fields in StackView.

The reason this works is you are giving permission for one of your controls to be a little smaller than the rest, which results in a whole number when the math doesn’t work out in your favor.

Do you have another layout problem you would like to see solved with UIStackViews?