Working with iOS 10 Auto Layout Constraints in Interface Builder
Previous | Table of Contents | Next |
An Introduction to Auto Layout in iOS 10 | An iOS 10 Auto Layout Example |
Learn SwiftUI and take your iOS Development to the Next Level |
By far the most productive and intuitive way to work with constraints is to do so using the auto layout features of Interface Builder. Not only does this avoid the necessity to write time consuming code (though for complex layout requirements some code will be inevitable) but it also provides instant visual feedback on constraints as they are configured.
Within this chapter, a simple example will be used to demonstrate the effectiveness of Auto Layout together with an in-depth look at the Auto Layout features of Interface Builder. The chapter will then move on to demonstrate the concepts of content hugging and constraint priorities.
A Simple Example of Auto Layout in Action
Before digging deeper into the Auto Layout features of Interface Builder, the first step in this chapter will be to quickly demonstrate the basic concept of Auto Layout. Begin, therefore, by creating a new Xcode project using the Single View Application template, entering AutoLayoutExample as the product name and choosing Universal from the devices menu.
Enabling and Disabling Auto Layout in Interface Builder
By default, Auto Layout is switched on for user interface design files, both for storyboard and individual XIB files. Begin by selecting the Main.storyboard file from the project navigator panel and select the main scene (the main scene in a storyboard can be identified by the arrow pointing to the left side) before displaying the File Inspector panel (View -> Utilities-> Show File Inspector). Located within this inspector is an option labeled Use Auto Layout as illustrated in Figure 19-1.
Figure 19-1
Below the Use Auto Layout option is another item titled Use Trait Variations. Trait Variations enable different Auto Layout settings to be configured for different device screen sizes from within a single storyboard file. So that this chapter can focus solely on Auto Layout, and to avoid the confusion of learning two concepts at once, turn off the Use Trait Variations option for this project.
When the confirmation panel appears (Figure 19-2), verify that the Keep size class data for menu is set to iPhone before clicking on the Disable Trait Variations button. Rest assured that trait variations and their relationship to Auto Layout constraints will be covered in considerable detail in the chapter entitled Using Trait Variations to Design Adaptive iOS User Interfaces.
Figure 19-2
Learn SwiftUI and take your iOS Development to the Next Level |
Figure 19-3
A problem arises, however, when the device rotates to landscape orientation. This can be demonstrated by compiling and running the application on a physical iPhone or iPad device or iOS Simulator in the usual way. Alternatively, the effect of an orientation change can be tested within the Interface Builder environment. To rotate to landscape mode, click on the View as: entry located in the status bar positioned along the bottom edge of the Interface Builder panel as highlighted in Figure 19-4 below:
Figure 19-4
When the button is clicked, the device type and orientation selection panel will appear. Within this panel (Figure 19-5) click on the landscape orientation option:
Figure 19-5
Learn SwiftUI and take your iOS Development to the Next Level |
Figure 19-6
Similar problems can occur when the application runs on different sizes of iPhone device which can be tested by clicking on the View as: button and selecting different device types.
Note that on larger and smaller display form factors in portrait orientation, the label is once again positioned incorrectly. Clearly layout is important, not only for handling device orientation, but also to ensure correct user interface appearance on different device models.
Prior to the introduction of Auto Layout, options to address this would have either involved using springs and struts or writing code to detect the rotation of the device and to move the label to the new location on the screen. Now, however, the problem can be solved using Auto Layout.
Begin by returning the view to portrait orientation so that the label is once again visible and select the label within the view canvas. Xcode provides a number of different ways to add constraints to a layout. These options will be covered later in this chapter but by far the easiest is to use the Auto Layout toolbar. With the label selected, click on the Add New Constraints menu (Figure 19-7):
Figure 19-7
The goal for this example is to add a constraint to the label such that the bottom edge of the label is always positioned the same distance from the bottom of the containing superview and so that it remains centered horizontally. To do this we are first interested in the Spacing to nearest neighbor section of this panel. This provides a visual representation of the view in question (in this case the label) which is represented by the square in the middle. Extending from each side of the square are faded and dotted I-beam icons that connect with fields containing values. The fact that the I-beams are dotted and faded indicates that these are constraints that have not been set. The values indicate the current distances within the layout of the corresponding side to the nearest neighbor. The “nearest neighbor” will either be the nearest view to that side of the currently selected view, or the corresponding side of the superview.
Select the constraint I-beam icon located beneath the view so that it appears in solid red (as shown in Figure 19-8) to indicate that the constraint is now set before clicking on the Add 1 Constraint button to add the constraint to the view.
Figure 19-8
Learn SwiftUI and take your iOS Development to the Next Level |
Figure 19-9
With the constraint appropriately configured, click on the Add 1 Constraint button to add the constraint to the view.
Having configured some constraints, rotate the orientation once again, noting this time that the label is visible and positioned sensibly. Testing different display form factors should also demonstrate that the constraints are working to keep the label correctly positioned for different devices.
Figure 19-10
In this example so far only a small subset of the Auto Layout features provided by Xcode has been used. In actual fact, Xcode provides a wide range of options and visual cues that are designed to ease the task of creating Auto Layout constraints.
The Auto Layout Features of Interface Builder
A number of features are provided in Xcode in order to assist in the implementation of Auto Layout based constraints. This section will present a guided tour of many of these features.
Suggested Constraints
When objects are added to a layout canvas, Interface Builder does not implement any default constraints on those views leaving the developer to add constraints as needed. There is, however, the option to have Interface Builder apply suggested constraints. When this option is used, Interface Builder will apply what it believes to be the correct constraints for the layout based on the positioning of the views. Suggested constraints can be added either to the currently selected view objects, or to an entire scene layout.
In situations where constraints are missing from a layout resulting in warnings, Interface Builder also provides the option to automatically add the constraints that it believes are missing.
The options to perform these tasks are accessed via the Resolve Auto Layout Issues menu in the toolbar as illustrated in Figure 19-11.
The top section of the menu represents tasks that relate to the currently selected views in the canvas, while the options in the lower section apply to all views in the currently selected view controller scene.
Figure 19-11
Most of the time, the suggested constraints will exactly match the required layout behavior and occasionally, the suggested constraints will be incorrect. Most of the time, however, the suggested constraints provide an excellent starting point for implementing Auto Layout. A typical process for designing a user interface might, therefore, involve positioning the views by dragging and dropping them into place, applying suggested constraints and then editing and fine tuning those constraints to perfect the layout.
To see suggested constraints in action, select the label view in the AutoLayoutExample project and select the Clear Constraints option from the Resolve Auto Layout Issues menu. At this point there are no constraints in the layout and the old positioning problem appears when the view is rotated. With the label still selected, choose the Reset to Suggested Constraints menu option listed under Selected Views. A review of the view canvas, and change of orientation should demonstrate that Interface Builder has suggested and applied the exact same constraints that we previously added manually.
Learn SwiftUI and take your iOS Development to the Next Level |
Visual Cues
Interface Builder includes a number of visual cues in the layout canvas to highlight the constraints currently configured on a view and to draw attention to areas where problems exist. When a view is selected within the layout canvas, the constraints that reference that view will be represented visually. Consider, for example, the label view created in our AutoLayoutExample application. When selected in the canvas, a number of additional lines appear as shown in Figure 19-12:
Figure 19-12
The vertical line that runs through the center of the label indicates the presence of a constraint that positions the label in the horizontal center of the parent view (analogous to the NSLayoutAttribute.CenterX attribute). If expressed as an equation, therefore, this would read as:
label.NSLayoutAttribute.CenterX = superview.NSLayoutAttribute.CenterX
The I-beam line running from the bottom edge of the label view to the bottom edge of the parent view indicates that a vertical space constraint is in place between the two views. The absence of any additional visual information on the line indicates that this is an equality constraint. Figure 19-13 shows an example of a “greater than or equal to” horizontal constraint between two button views:
Figure 19-13
The horizontal line running beneath the Button label text indicates that constraints are in place to horizontally align the content baseline (represented by NSLayoutAttributeBaseline) of the two buttons.
Width constraints are indicated by an I-beam line running parallel to the edge of the view in the corresponding dimension. The text view object in Figure 19-14, for example, has a “greater than or equal to” width constraint configured:
Figure 19-14
Highlighting Constraint Problems
Interface Builder also uses a range of visual cues and decorations to indicate that constraints are either missing, ambiguous or in conflict. Valid and complete Auto Layout configurations are drawn using blue lines. When part of a layout is ambiguous the constraint lines are orange.
Ambiguity typically occurs when a constraint is missing. Take for example the label view used earlier in the chapter. If only the horizontal center constraint is set, that constraint line will appear in orange because Auto Layout does not know where to position the view in the vertical plane. Once the second constraint is set between the bottom edge of the label and the bottom of the superview the constraint line will turn blue to indicate that the layout is no longer ambiguous.
Red constraint lines are used to indicate that constraints are in conflict. Consider, for example, a view object on which two width constraints have been configured, each for a different width value. The Auto Layout system categorizes such a situation as a constraint conflict and Interface Builder draws the offending constraint lines on the layout canvas in red. Figure 19 15, for example, illustrates a conflict where one constraint is attempting to set the width of a view to 110 points while a second constraint dictates that the width must be greater than or equal to 120 points:
Figure 19-15
Learn SwiftUI and take your iOS Development to the Next Level |
Figure 19-16
Select the new Text Field object and, using the Add New Constraints menu, establish a Spacing to nearest neighbor constraint from the top of the text view to the top of the superview. Using the Align menu, add another constraint that aligns the view with the horizontal center in the container. Having established these constraints, review the constraint lines within the view canvas. As outlined in Figure 19-17, the horizontal center constraint appears in orange with a number assigned to it. A dotted box also appears on this line, level with the text view object. Interface Builder is attempting to warn us that the size and position of this view is going to resemble the dotted orange box at run time, and not the size and position currently shown for the view in the canvas. The number on the horizontal center constraint tells us that the horizontal position of the object is going to be a specific number of points to the left of the current position.
Figure 19-17
To reset the view to the size and position dictated by the constraints when using Xcode 8.1 or later so that the canvas matches the runtime layout, simply select the Text View object and click on the Update Frames button located in the Interface Builder status bar as highlighted in Figure 19-18. For Xcode 8.0, use one of the Update Frames options contained within the Resolve Auto Layout Issues menu:
Figure 19-18
The canvas will subsequently update to reflect the correct layout appearance (Figure 19-19):
Figure 19-19
If, on the other hand, the text view had been positioned correctly (in other words the visual position was correct but the constraints were wrong), the current constraints could have been adjusted to match the actual position of the view using the Update Constraint Constants option of the Resolve Auto Layout Issues menu.
Viewing, Editing and Deleting Constraints
All of the constraints currently set on the views of a user interface may be viewed at any time from within the Document Outline panel that is positioned to the left of the Interface Builder canvas area. Hidden by default, this panel can be displayed by clicking on the button in the bottom left-hand corner of the storyboard canvas (marked by the arrow in Figure 19-20).
Figure 19-20
Within this outline, a category listed as Constraints will be present which, when unfolded, will list all of the constraints currently configured for the layout. Note that when more than one container view is present in the view hierarchy there will be a separate constraints list for each one. Figure 19-21, for example, lists the constraints for the user interface represented in Figure 19-12 above:
Figure 19-21
Learn SwiftUI and take your iOS Development to the Next Level |
The details of a particular constraint may be viewed and edited at any time using a variety of methods. One method is simply to double-click on the constraint line in the canvas to display a constraint editing panel:
Figure 19-22
Another option is to select the constraint either from within the layout canvas or in the Document Outline panel. Once selected, display the Attributes Inspector in the Utilities panel (View -> Utilities -> Show Attributes Inspector) to view and edit the properties of the constraint. Figure 19-23 illustrates the settings for an equality spacing constraint.
Figure 19-23
A listing of the constraints associated with a specific view can be obtained by selecting that view in the layout canvas and displaying the Size Inspector in the Utilities panel. Figure 19-24, for example, lists two constraints that reference the currently selected view. Clicking on the edit button on any constraint will provide options to edit the constraint properties. In addition, constraints can be removed by selecting them in the layout canvas and pressing the keyboard Delete key.
Figure 19-24
Creating New Constraints in Interface Builder
New user constraints can be created in Interface Builder using a variety of approaches, keeping in mind that constraints can relate to more than one view at a time. For example to configure an alignment constraint, all of the views which are to be included in the alignment operation must be selected before creating the constraints.
One of the easiest ways, as demonstrated earlier in this chapter, is to use the various options in the toolbar in the bottom right-hand corner of the storyboard canvas.
Another useful option is simply to Ctrl-click within a view and then drag the resulting line outside of the boundary of the view. On releasing the line, a context menu will appear providing constraint options. The menu options provided will depend on the direction in which the line was dragged. If the line is dragged downwards, for example, the menu will include options to add a constraint to the bottom of the view, or to center vertically within the container. Dragging horizontally, on the other hand, provides the option to attach to the corresponding edge of the container or to center horizontally. Dragging the line to another view in the canvas will provide options (Figure 19-25) to set up spacing, alignment and size equality constraints between those views.
Figure 19-25
Adding Aspect Ratio Constraints
The height and width of a view can be constrained to retain aspect ratio by Ctrl-clicking in the view, dragging diagonally and then releasing. In the resulting menu, selecting Aspect Ratio ensures that regardless of whether the view shrinks or grows, the current aspect ratio will be retained.
Figure 19-26
Learn SwiftUI and take your iOS Development to the Next Level |
Resolving Auto Layout Problems
Another advantage of implementing Auto Layout constraints in Xcode is that a number of features are available in Xcode to assist in resolving problems.
In the first instance, descriptions of current issues can be obtained by clicking on the yellow warning triangle in the top right-hand corner of the canvas area:
Figure 19-27
Solutions to some problems may be implemented by using the options in the Resolve Auto Layout Issues menu to perform tasks such as automatically adding missing constraints or resetting to suggested constraints.
More detailed resolution options are available from within the document outline panel. When issues need to be resolved, a red circle with a white arrow appears next to the corresponding view controller name in the outline panel as shown in Figure 19-28:
Figure 19-28
Clicking on the red circle displays all current layout issues listed by category:
Figure 19-29
Hovering over a category title (for example Missing Constraints) will display an information symbol which, when clicked, will display a detailed description of the problem type.
Clicking on the error or warning symbol will display a panel providing one or more possible solutions together with a button to apply the selected change:
Figure 19-30
Summary
Within this chapter we have looked at a very simplistic example of the benefits of using Auto Layout in iOS user interface design. The remainder of the chapter has been dedicated to providing an overview of the Auto Layout features that are available in Interface Builder.
Learn SwiftUI and take your iOS Development to the Next Level |
Previous | Table of Contents | Next |
An Introduction to Auto Layout in iOS 10 | An iOS 10 Auto Layout Example |