Part 1 discusses the two layout options, then dives in on springs and struts. Part 2 discusses the new Auto Layout option available in iOS 6 and later. Part 3 takes tutorial on Auto Layout to the next level!
Auto Layout is a descriptive layout system that supports more complex user-interface layouts. As you will learn when we cover creating multi-lingual applications later in this series, it also makes internationalization much easier. Auto Layout is a complete replacement for springs and struts, but remember that it can only be used in Apps running on iOS 6 or later!
With Auto Layout, you create descriptions known as constraints that specify how you want your controls positioned and resized. You can specify the relative size and position of a control with respect to the view that contains it or with respect to other controls in the view. You can also use constraints to specify geometric properties of a control such as height and width. From these constraints, Auto Layout calculates the appropriate position and size of your controls at run time when the view first loads and when the size of the view changes, such as when the user changes the device orientation.
Let’s dive in with an example so you can see first hand how this works. To get the sample code for this tutorial, click on the following link:
- In Xcode, open the AutolayoutDemo project in this tutorial’s sample code.
- In the Project Navigator, select the MainStoryboard file and then go to the File Inspector (click the first button on the left in the Inspector toolbar). Note that the Use Autolayout option is selected.
- Drag a Round Rect Button from the Object Library and position it at the bottom of the main scene in the storyboard. When you see the horizontal and vertical guide lines as shown in Figure 8.14, let go of the mouse button to drop the button on the scene.
- Go to the Size Inspector (the second button from the right in the Inspector toolbar) and you will see two constraints at the bottom of the panel (Figure 8.16).
- Align Center X to: Superview - This constraint specifies that the button should be vertically aligned to the center of the superview (the view that contains the button).
- Bottom Space to: Superview Equals: Default - This constraint specifies that the space between the bottom of the button and the superview is the default space recommended for UI objects.
Figure 8.14 Position the button at the bottom of the scene until you see horizontal and vertical guide lines.Notice the long vertical line in the center of the scene, as well as the small “I” bar between the bottom of the button and the bottom of the scene (Figure 8.15). These are constraints that Interface Builder automatically added to the view.
Figure 8.15 When you select a UI control, its constraints are displayed in the design surface.
If you select a constraint, you can see more details about it. Although you can click on a constraint directly in the design surface to select it, it’s usually easier to go to the Size Inspector where constraints for the currently selected control are also shown.
Figure 8.16 The Size Inspector displays constraints for the object currently selected in the design surface.
These specific constraints were added by Interface Builder because you dropped the button on the view when the center-alignment and bottom-alignment guidelines appeared.
- Hover your mouse pointer over the Align Center constraint in the Size Inspector. The associated constraint is highlighted in the design surface as shown in Figure 8.17. This provides visual confirmation that you are looking at the correct constraint.
- Go to the Document Outline pane and you can see constraints are also listed there (Figure 8.18). Selecting a constraint in the Document Outline pane highlights the corresponding constraint and associated control(s) in the design surface.
- Now let’s see how the button looks at run time. In Xcode, click the Run button. When the App appears in the Simulator, you will see the button is centered at the bottom of the view (Figure 8.19).
- Go to the Simulator menu and select Hardware > Rotate Left. Notice the button is still centered at the bottom of the view (Figure 8.20).
Figure 8.17 Hover over a constraint in the Size Inspector to see the corresponding constraint in the design surface.
Figure 8.18 Constraints in the Document Outline pane
Figure 8.19 The button centered at the bottom of the view
When you center a button at the bottom of a view using springs and struts, it hard-codes the position of the button to that location. In order to keep the button centered when the device orientation changes, you have to explicitly specify this by selecting the appropriate struts in the Size Inspector.
With Auto Layout, all you had to do was place the button in the bottom center of the view and it positioned itself automatically. This is much easier!
Now let’s take a closer look at the constraints that are automatically created for you by Interface Builder.
- Go back to Xcode and click the Stop button to stop the App from running in the Simulator.
- In the Document Outline pane, select the Vertical Space constraint. This highlights the button’s vertical constraint at the bottom of the view (the “I“ bar located below the button) as shown in Figure 8.21.
- Next, go to the Attributes Inspector (click the third button from the right in the Inspector toolbar). You will see the constraint attributes that are shown in Figure 8.22.
Figure 8.22 Vertical-space constraint attributes
- Relation – The three values for this attribute are:
- Less Than or Equal
- Greater Than or Equal
In the context of the vertical-space constraint, this indicates if the vertical space is less than or equal to, equal to, or greater than or equal to the specified amount of space.
- Constant - This attribute allows you to specify the amount of vertical space in points.
- Standard - When this option is selected, it indicates the “standard” amount of space is specified between the associated control and the parent view or another control. The standard space is indicated in the design surface by the appearance of guide lines as you position a control in the design surface.
- Priority - Specifies the priority of this constraint in relation to other constraints. This value can be anywhere between 1 and 1000, where 1000 indicates the constraint is required. Anything less than 1000 indicates the constraint is optional. At run time, Auto Layout compares conflicting constraints. The constraint with the higher priority is applied, and the constraint with the lower priority is not applied.
- Relation – The three values for this attribute are:
Figure 8.21 The button’s vertical constraint is highlighted.
The constraint shown in Figure 8.22 could be read as “Require the vertical space between the bottom of the button and the bottom of the view to be the standard spacing for iOS Apps.”
When you change the size or position of a control at design time, Interface Builder deletes old constraints and adds new ones based on your changes. Let’s take a look at some other constraints that are created automatically.
- In the design surface, drag the button to the bottom-left corner of the view until the horizontal and vertical guide lines appear (Figure 8.23) and then release the mouse button.
- The Size Inspector provides more meaningful information about a constraint, so go to the Size Inspector and you will see the constraints shown in Figure 8.25.
- To see the leading-space constraint’s attributes, click the down arrow on the right side of the constraint and select Select and Edit… from the popup menu (Figure 8.26).
- This unselects the button, selects the constraint in the design surface, and displays the attributes shown in Figure 8.27 in the Attributes Inspector.
Figure 8.27 The constraint’s Direction attribute
Notice the Direction attribute, which lets you specify the direction of the horizontal space. The choices are:
- Leading to Trailing - In English, leading is left and trailing is right. In right-to-left languages, leading is right and trailing is left.
- Left to Right - If you don’t want the horizontal space to change when the language changes, you can specify you always want it to be left to right.
- Go back to the design surface, drag the button to the bottom-right corner of the view until the horizontal and vertical guide lines appear (Figure 8.28) and then release the mouse button.
- Go to the Size Inspector and you can see that positioning the button in this location deletes the leading space constraint and creates a Trailing Space constraint shown at the top of Figure 8.29.
- Let’s check out one more constraint. In the design surface, drag the button to the top center of the view until the horizontal and vertical guide lines appear (Figure 8.30), and then let go of your mouse button.
- Go to the Size Inspector and you can see that positioning the button in this location deletes the trailing space constraint and adds a new Top Space constraint shown at the top of Figure 8.31.
- We’re finished looking at the different button constraints, so in the design surface, drag the button back down to the bottom center of the view until the horizontal and vertical guide lines appear, and then let go of your mouse button. This should restore the Bottom Space and Align Center X constraints shown in Figure 8.16.
Figure 8.23 The button in the bottom left corner of the view
This deletes the Center X Alignment constraint and creates a Horizontal Space constraint, which can be seen in the Document Outline pane (Figure 8.24).
Figure 8.24 The Horizontal Space constraint
Figure 8.25 The Leading Space constraint
The constraint is more generically called Horizontal Space in the Document Outline pane, and more specifically called a Leading Space constraint in the Size Inspector.
In English, leading space indicates the space between the left side of the view and the left side of the UI control. In right-to-left languages such as Hebrew and Arabic, it indicates the space between the right side of the view and the right side of the control.
Figure 8.26 View the leading-space constraint attributes.
Figure 8.28 Position the button in the bottom-right corner.
Figure 8.29 The Trailing Space constraint
The trailing-space constraint has the same attributes as the leading-space constraint, so we don’t need to go to the Attributes Inspector to check them out.
Figure 8.30 Position the button at the top center
Figure 8.31 The new Top Space constraint
The top-space constraint has the same attributes as the bottom-space constraint, so we don’t need to go to the Attributes Inspector.
Creating User Constraints
The constraints that are created automatically for you by Interface Builder are only a best guess, so sometimes you need to add your own constraints or modify an existing constraint to get the exact resizing and repositioning you need for the controls in your App.
When you manually add a new constraint or modify an existing constraint, it creates something called a user constraint. Let’s give it a try.
- If it’s not already open, in Xcode, open the AutolayoutDemo project.
- Select the button at the bottom of the scene, and then go to the Attributes Inspector. Change the Title attribute to Done and press Enter. This adds a new Width constraint, which you can see in the design surface below the button (Figure 8.32).
- Select the Width constraint in the Document Outline and then go to the Attributes Inspector. You will see the attributes shown in Figure 8.34.
To see what I mean, let’s connect the button to an outlet that’s already been created for you. To do this, first display the Assistant Editor (in Xcode’s toolbar, click the center button in the Editor button set). This should display the ViewController.h file in the Assistant Editor (if it doesn’t, select the file in the Assistant Editor’s jump bar).
- Next, hold the Control key down, click on the button and drag down to the btnTest outlet in the ViewController.h file. When the Connect Outlet popup appears (Figure 8.35), let go of the mouse to connect the button to the outlet.
- Now go to the Project Navigator and select the ViewController.m file to see the following code in the viewDidLoad method that stores a longer text string to the Done button’s Title:
- Click Xcode’s Run button, and when the App appears in the Simulator, you can see the title of the button is clipped as shown in Figure 8.36.
Figure 8.32 The Width constraint
You can also see the constraint in the Document Outline pane listed under the button (Figure 8.33). Constraints that are specific to a single control are listed directly under the control.
Figure 8.33 Width constraint in the Document Outline pane
Figure 8.34 The width constraint attributes
Notice there is no Standard option as there was with the spacing constraints, just a Constant setting that specifies the width of the object in points. This indicates the button will always be 73 points wide.
That might be OK if the text of the button always stays the same, but if the text of the button changes at run time (as it does if your App supports multiple languages), this hard-coded setting won’t work well.
Figure 8.35 Connect the button to the btnTest outlet.
[self.btnTest setTitle:@"Completed!" forState:UIControlStateNormal];
Figure 8.36 The button title is clipped.That’s because the constraint told the button that it could only be 73 points wide—not wide enough to display the complete title.
There are a few ways you can fix this problem. To start, let’s modify the constraint to allow the button to increase in width as its content changes.
- Go back to Xcode and click the Stop button.
- Turn off the Assistant Editor by going to the Xcode toolbar and clicking the left button in the Editor button group.
- In the Project Navigator, select the MainStoryboard file, then go to the Document Outline pane and select the Width constraint as shown in Figure 8.33.
- Go to the Attributes Inspector and change the Relation attribute to Greater Than or Equal as shown in Figure 8.34.
- Let’s see how this works at run time. Click Xcode’s Run button, and when the App appears in the Simulator, you should see the full title in the button as shown in Figure 8.39. That’s because you let the button decide how big it should be. The button has an intrinsic size that is determined by its content. Usually, it’s best to let a button decide its size rather than hard-coding a constraint that sets its size to a hard-coded value.
- Go back to Xcode and click the Stop button.
- Select the Done button in the design surface, go to the Xcode menu, and then select Editor > Size to Fit Content. Notice when you do this that the Width constraint completely disappears. As it turns out, it was a constraint that was automatically added to the view by Interface Builder that was completely unnecessary. You will learn how to avoid this in the next section!
- Click the Run button again and when the App appears in the Simulator, notice the content is not clipped!
Figure 8.37 Set the Relation to Greater Than or Equal.
Changing this default constraint created by Interface Builder changes the automatic constraint to a user constraint. Notice it’s color has changed from purple to blue in the Document Outline pane (Figure 8.38). In addition, the “I” constraint bar in the view is bolded. These are great visual cues so you can easily identify which user constraints you have changed or manually added.
Figure 8.38 Width is now a user constraint.
Figure 8.39 The button title is no longer clipped!
Usually, it’s best to let a button decide its size rather than hard-coding a constraint that sets its size to a hard-coded value.
In this set of steps, I wanted to show you how to change the Relation attribute of a constraint to allow it to expand to its intrinsic size. Ultimately, there is even a better way to do this.
Avoiding Unnecessary Constraints
In the previous section, you saw that, at times, Interface Builder adds unnecessary constraints to your view. Since you want to keep your views as simple as possible, you should only have the constraints you absolutely need. In the next set of steps you will add a label to the view and learn how to avoid some of these unnecessary constraints.
- If it’s not already open, in Xcode, open the AutolayoutDemo project.
- If it’s not already selected, go to the Project Navigator and select the Mainstoryboard file.
- Drag a Label from the Object Library and position in at the top center of the scene. When you see the guide lines appear (Figure 8.40), release the mouse button to drop the label in place.
- With the label still selected, go to the Attributes Inspector (third button from the right in the Inspector toolbar), and set the label’s Text to Oliver!
- Double-click the label in the design surface and press Enter. This removes the width constraint!
Figure 8.40 Drop a label in the top center of the scene.
Just as you would expect, this adds Center X Alignment and Vertical Space constraints for the label (Figure 8.41). If you look closely, you can see that the label is center aligned to the button rather than the view (the text Label – Label – Button – Done indicates the Label named Label is aligned to the Button named Done. This is standard behavior when you are centering multiple controls in the same view.
Figure 8.41 The new label constraints
Notice this adds a width constraint as shown in the design surface (Figure 8.42) and clips the label text.
Figure 8.42 The label’s width constraint
As you learned in the previous section, width constraints created in this way are usually not desirable. I’ll show you an easy way to get rid of them.
The lesson to take away from this is that you should set a label’s text by double-clicking in the design surface rather than setting it in the Attributes Inspector. Note that this trick works with other controls that have a Text attribute such as buttons and segmented controls.
In Part 3 of this tutorial, we’ll take the lessons on Auto Layout even further!