13
Stack Views

You have been using Auto Layout throughout this book to create flexible interfaces that scale across device types and sizes. Auto Layout is a very powerful technology, but with that power comes complexity. Laying out an interface well often needs a lot of constraints, and it can be difficult to create dynamic interfaces due to the need to constantly add and remove constraints.

Often, an interface (or a subsection of the interface) can be laid out in a linear fashion. Think about the other applications you wrote: The Quiz application from Chapter 1 consisted of four subviews that were laid out vertically. The same is true for the WorldTrotter application; the ConversionViewController had a vertical interface consisting of a text field and a few labels.

Interfaces that have a linear layout are great candidates for using a stack view. A stack view is an instance of UIStackView that allows you to create a vertical or horizontal layout that is easy to lay out and manages most of the constraints that you would typically have to manage yourself. Perhaps best of all, you are able to nest stack views within other stack views, which allows you to create truly amazing interfaces in a fraction of the time.

In this chapter, you are going to continue working on Homepwner to create an interface for displaying the details of a specific Item. The interface that you create will consist of multiple nested stack views, both vertical and horizontal (Figure 13.1).

Figure 13.1  Homepwner with stack views

Screenshot shows the workspace window in Xcode.

Using UIStackView

You are going to create an interface for editing the details of an Item. You will get the basic interface working in this chapter, and then you will finish implementing the details in Chapter 14.

At the top level, you will have a vertical stack view with four elements displaying the item’s name, serial number, value, and date created (Figure 13.2).

Figure 13.2  Vertical stack view layout

Figure shows a vertical stack view of four labels: Name, Serial, Value, and Date Created that are aligned one below the other. The sizes of the labels are given by rectangular sections, with the date created section larger than the other sections, that are all of equal sizes.

Open your Homepwner project and then open Main.storyboard. Drag a new View Controller from the object library onto the canvas. Drag a Vertical Stack View from the object library onto the view for the View Controller. Add constraints to the stack view to pin it to the leading and trailing margins, and pin the top and bottom edges to be 8 points from the top and bottom layout guides.

Now drag four instances of UILabel from the object library onto the stack view. From top to bottom, give these labels the text Name, Serial, Value, and Date Created (Figure 13.3).

Figure 13.3  Labels added to the stack view

Screenshot of a stack view is shown. Four labels: Name, Serial, Value, and Date Created are added to the stack. A battery level indicator is present at the top-right corner.

You can see a problem right away: The labels all have a red border (indicating an Auto Layout problem) and there is a warning that some views are vertically ambiguous. There are two ways you can fix this issue: by using Auto Layout, or by using a property on the stack view. Let’s work through the Auto Layout solution first because it highlights an important aspect of Auto Layout.

Implicit constraints

You learned in Chapter 3 that every view has an intrinsic content size. You also learned that if you do not specify constraints that explicitly determine the width or height, the view will derive its width or height from its intrinsic content size. How does this work?

It does this using implicit constraints derived from a view’s content hugging priorities and its content compression resistance priorities. A view has one of these priorities for each axis:

  • horizontal content hugging priority

  • vertical content hugging priority

  • horizontal content compression resistance priority

  • vertical content compression resistance priority

Content hugging priorities

The content hugging priority is like a rubber band that is placed around a view. The rubber band makes the view not want to be bigger than its intrinsic content size in that dimension. Each priority is associated with a value from 0 to 1000. A value of 1000 means that a view cannot get bigger than its intrinsic content size on that dimension.

Let’s look at an example with just the horizontal dimension. Say you have two labels next to one another with constraints both between the two views and between each view and its superview, as shown in Figure 13.4.

Figure 13.4  Two labels side by side

A view shows two labels: “Achieve” and “Nerdvana” of equal sizes placed side by side.

This works great until the superview becomes wider. At that point, which label should become wider? The first label, the second label, or both? As Figure 13.5 shows, the interface is currently ambiguous.

Figure 13.5  Ambiguous layout

Two wide superviews containing the labels: Achieve and Nerdvana are shown. In the first view, the label achieve is shown to be wider, and in the second superview, the label Nerdvana is shown wider.

This is where the content hugging priority becomes relevant. The view with the higher content hugging priority is the one that does not stretch. You can think about the priority value as the strength of the rubber band. The higher the priority value, the stronger the rubber band, and the more it wants to hug to its intrinsic content size.

Content compression resistance priorities

The content compression resistance priorities determine how much a view resists getting smaller than its intrinsic content size. Consider the same two labels from Figure 13.4. What would happen if the superview’s width decreased? One of the labels would need to truncate its text (Figure 13.6). But which one?

Figure 13.6  Compressed ambiguous layout

Two rectangular views containing the labels “Achieve” and “Nerdvana” are shown. In the first view, the label Achieve is truncated to “Ach…” In the second view, the label Nerdvana is truncated as “Nerdv…”

The view with the greater content compression resistance priority is the one that will resist compression and, therefore, not truncate its text.

With this knowledge, you can now fix the problem with the stack view.

Select the Date Created label and open its size inspector. Find the Vertical Content Hugging Priority and lower it to 249. Now the other three labels have a higher content hugging priority, so they will all hug to their intrinsic content height. The Date Created label will stretch to fill in the remaining space.

Stack view distribution

Let’s take a look at another way of solving the problem. Stack views have a number of properties that determine how their content is laid out.

Select the stack view, either on the canvas or using the document outline. Open its attributes inspector and find the section at the top labeled Stack View. One of the properties that determines how the content is laid out is the Distribution property. Currently it is set to Fill, which lets the views lay out their content based on their intrinsic content size. Change the value to Fill Equally. This will resize the labels so that they all have the same height, ignoring the intrinsic content size (Figure 13.7). Be sure to read the documentation for the other distribution values that a stack view can have.

Figure 13.7  Stack view set to fill equally

Screenshot of a view controller shows a stack view with four labels: Name, Serial, Value, and Date Created of equal sizes that are distributed uniformly.

Change the Distribution of the stack view back to Fill; this is the value you will want going forward in this chapter.

Nested stack views

One of the most powerful features of stack views is that they can be nested within one another. You will use this to nest horizontal stack views within the larger vertical stack view. The top three labels will have a text field next to them that displays the corresponding value for the Item and will also allow the user to edit that value.

Select the Name label on the canvas. Click the second icon from the left in the Auto Layout constraints menu: The Down Arrow icon is shown.. This will embed the selected view in a stack view.

Select the new stack view and open its attributes inspector. The stack view is currently a vertical stack view, but you want it to be a horizontal stack view. Change the Axis to Horizontal.

Now drag a Text Field from the object library to the right of the Name label. Because labels, by default, have a greater content hugging priority than text fields, the label hugs to its intrinsic content width and the text field stretches. The label and the text field currently have the same content compression resistance priorities, which would result in an ambiguous layout if the text field’s text was too long. Open the size inspector for the text field and set its Horizontal Content Compression Resistance Priority to 749. This will ensure that the text field’s text will be truncated if necessary, rather than the label.

Stack view spacing

The label and text field look a little squished because there is no spacing between them. Stack views allow you to customize the spacing between items.

Select the horizontal stack view and open its attributes inspector. Change the Spacing to be 8 points. Notice that the text field shrinks to accommodate the spacing, because it is less resistant to compression than the label.

Repeat these steps for the Serial and Value labels:

  1. Select the label and click the Stack view spacing icon.

  2. Change the stack view to be a horizontal stack view.

  3. Drag a text field onto the horizontal stack view and change its horizontal content compression resistance priority to be 749.

  4. Update the stack view to have a spacing of 8 points.

There are a couple of other tweaks you will want to make to the interface: The vertical stack view needs some spacing. The Date Created label should have a center text alignment. And the Name, Serial, and Value labels should be the same width.

Select the vertical stack view, open its attributes inspector, and update the Spacing to be 8 points. Then select the Date Created label, open its attributes inspector, and change the Alignment to be centered. That solves the first two issues.

Although stack views substantially reduce the number of constraints that you need to add to your interface, some constraints are still important. With the interface as is, the text fields do not align on their leading edge due to the difference in the widths of the labels. (The difference is not very noticeable in English, but it becomes more pronounced when localized into other languages.) To solve this, you will add leading edge constraints between the three text fields.

Control-drag from the Name text field to the Serial text field and select Leading. Then do the same for the Serial text field and the Value text field. The completed interface will look like Figure 13.8.

Figure 13.8  Final stack view interface

A stack view with three labels is shown.

Stack views allow you to create very rich interfaces in a fraction of the time it would take to configure them manually using constraints. Constraints are still added, but they are being managed by the stack view itself instead of by you. Stack views allow you to have very dynamic interfaces at runtime. You can add and remove views from stack views by using addArrangedSubview(_:), insertArrangedSubview(_:at:), and removeArrangedSubview(_:). You can also toggle the hidden property on a view in a stack view. The stack view will automatically lay out its content to reflect that value.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset