Auto Layout to the rescue!
You will now see how to accomplish this same effect with Auto Layout. First, remove willAnimateRotationToInterfaceOrientation:duration: from ViewController.m, because you’re now going to do this without writing any code.
Select ViewController.xib and in the File inspector panel, check the “Use Autolayout” box to enable Auto Layout for this nib file:
Note: Auto Layout is always enabled for the entire nib or storyboard file. All the views inside that nib or storyboard will use Auto Layout if you check that box.
Run the app and rotate to landscape. It should give the same messed up layout that it did earlier:
Let’s put Auto Layout into action. Hold down the Cmd key while you click on the two views on the top (the green and yellow ones), so that both are selected. From Xcode’s Editor menu, select Pin\Widths Equally:
Select the same two views again and choose Editor\Pin\Horizontal Spacing. (Even though the two views appear selected after you carry out the first Pin action, do note that they are in a special layout relationship display mode. So you do have to reselect the two views.)
In the Document Outline on the left, you’ll notice a new section named “Constraints”. This section was added when you enabled Auto Layout for the nib. You will learn all about what these constraints are and how they operate in the next section.
For now, locate the one named “Horizontal Space (170)” and delete it from the list:
Run the app and rotate to landscape. That looks better already – the views at the top now have the proper widths and padding – but you’re not quite there yet:
Hold down Cmd and select all three views. From the Editor menu, choose Pin\Heights Equally.
Now select the top-left corner view and the bottom view (using Cmd as before), and choose Editor\Pin\Vertical Spacing.
Finally, remove the “Vertical Space (240)” constraint from the list.
If you select all three views at the same time, Interface Builder should show something like this:
The blue “T-bar” shaped things represent the constraints between the views. It might look a bit scary, but it is actually quite straightforward once you learn what it all means.
Run the app and… voila, everything looks good again, all without writing a single line of code!
Cool, but what exactly did you do here? Rather than requiring you to hard-code how big your views are and where they are positioned, Auto Layout lets you express how the views in your layout relate to each other.
You have put the following relationships – what is known as constraints – into the layout:
- The top-left and top-right views always have the same width (that was the first pin widths equally command).
- There is a 20-point horizontal padding between the top-left and top-right views (that was the pin horizontal spacing).
- All the views always have the same height (the pin heights equally command).
- There is a 20-point vertical padding between the two views on top and the one at the bottom (the pin vertical spacing).
And that is enough to express to Auto Layout where it should place the views and how it should behave when the size of the screen changes.
Note: There are also a few other constraints that were brought over from the springs-and-struts layout when you toggled the “Use Autolayout” checkbox. For each of the margins between the views and the edges of the screen there is now a constraint that basically says: “this view always sits at a 20-points distance from the top/bottom/left/right edge.”
You can see all your constraints in the Document Outline. If you click on a constraint in the Document Outline, Interface Builder will highlight where it sits on the view by drawing a white outline around the constraint and adding a shadow to it so that it stands out:
Constraints are real objects (of class NSLayoutConstraint) and they also have attributes. For example, select the constraint that creates the padding between the two top views (it is named “Horizontal Space (20)”) and then switch to the Attributes inspector. There you can change the size of the margin by editing the Constant field.
Set it to 100 and run the app again. Now the margin is a lot wider:
Auto Layout is a lot more expressive than springs and struts when it comes to describing the views in your apps. In the rest of this tutorial, you will learn all about constraints and how to apply them in Interface Builder to make different kinds of layouts.
How Auto Layout works
As you’ve seen in the test drive above, the basic tool in Auto Layout is the constraint. A constraint describes a geometric relationship between two views. For example, you might have a constraint that says:
“The right edge of label A is connected to the left edge of button B with 20 points of empty space between them.”
Auto Layout takes all of these constraints and does some mathematics to calculate the ideal positions and sizes of all your views. You no longer have to set the frames of your views yourself – Auto Layout does that for you, entirely based on the constraints you have set on those views.
Before Auto Layout, you always had to hard-code the frames of your views, either by placing them at specific coordinates in Interface Builder, by passing a rectangle into initWithFrame:, or by setting the view’s frame, bounds or center properties.
For the app that you just made, you specifically set the frames to:
You also set autosizing masks on each of these views:
That is no longer how you should think of your screen designs. With Auto Layout, all you need to do is this:
The sizes and positions of the views are no longer important; only the constraints matter. Of course, when you drag a new button or label on to the canvas it will have a certain size and you will drop it at a certain position, but that is only a design aid that you use to tell Interface Builder where to put the constraints.