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!
User Interface Layout Options
Starting in iOS 6, there are two main ways you can specify the size and position of UI controls in your App so that all objects reposition and resize properly when the user rotates the iOS device, or when designing a UI that will run on both the iPhone and iPad:
- Springs and Struts
- Auto Layout
This tutorial details how and when to use older “springs and struts” technology versus the new Auto Layout.
A storyboard’s Use Autolayout setting (found in the File Inspector as shown in Figure 8.1) determines which user-interface layout option you are using.
Figure 8.1 The Autolayout setting
If this check box is unselected (it is for storyboards created using Xcode 4.4 or older), the storyboard uses springs and struts for laying out the user interface. If it’s selected (it is for storyboards created using Xcode 4.5 or newer), the storyboard uses the new Auto Layout approach.
Springs and Struts
The classic springs and struts approach to laying out your user interface works well for simple user interfaces. However, for more complex user interfaces, you need to write code to size and position controls when using springs and struts.
So, why use springs and struts at all? The primary reason is to allow your App to be installed on devices that are running an older version of iOS (prior to iOS 6).
In contrast with the hard-coded nature of springs and struts, the new Auto Layout feature is a descriptive layout system. It supports far more complex user-interface layouts, so you rarely need to write code to ensure your user-interface positions and resizes properly as the size of the parent view changes.
Unfortunately, Auto Layout can only be used in iOS 6 or later. So, if you want to make you App available to users who are using an older version of iOS, you need to stick with the springs and struts layout.
This is the reason we will still cover the older springs and struts technology. Let’s dive in!
Working with Springs and Struts
When the Autolayout setting is unselected in a storyboard, the Size Inspector looks like Figure 8.2.
Figure 8.2 The Size Inspector with Autolayout turned off
The upper portion of the Size Inspector allows you to specify the size and location of the UI object that is currently selected in the design surface. The X coordinate specifies the number of points the selected object is positioned from the left side of the view. The Y coordinate specifies the number of points from the top of the view. The Width and Height properties specify the size of the UI object.
Often, you want the size and position of a user-interface object to change when its parent view’s size (height and width) changes. The view size can change when:
- The user rotates the iOS device.
- The App runs on different iOS devices such as the iPhone 3.5-inch, iPhone 4-inch, iPad, the iPad mini, and whatever new device size Apple produces in the future.
The Autosizing section at the bottom left corner of the Size Inspector allows you to specify if and how you want a user-interface objects’ size and position to change. The outer square in the Autosizing section represents the four sides of the view: top, bottom, left, and right. The inner square represents the currently selected UI object.
You use the red “I” bars, known as “struts,” between the two squares to indicate how you want the selected object to be positioned as the size of the view changes. The struts represent anchors.
If a strut is dark red, it indicates the control is anchored to the corresponding side of the view. So, in Figure 8.2, the selected object is anchored to the top and left sides of the view. This means that, regardless of how the width or height of the view changes, the object is anchored to the top and left side of the view at the position specified in the X and Y settings.
There are two red arrows, known as “springs,” inside the inner square that indicate how you want the selected object to resize. The horizontal spring indicates width and the vertical spring represents height.
If you want the selected object’s width to stretch with the width of the view, select the horizontal spring. If you want the selected object’s height to stretch with the height of the view, select the vertical spring. In Figure 8.3, both springs are selected, so the object’s height and width stretches with the height and width of the view.
Figure 8.3 Both springs are selected.
On the right side of the Autosizing section is an Example image (Figure 8.4) that shows the relative location and size of the selected object, shown in red, positioned on a white rectangle that represents the view.
Figure 8.4 Autosizing Example on the right
If you hover your mouse pointer anywhere in the Autosizing section, the Example image animates, first expanding the width and height of the view and then contracting. This allows you to see how the position and size of the selected object changes as the size of the view changes.
At the very bottom of the Size Inspector is an Arrange list box, which allows you to position or size the selected object easily by using these options:
- Center Horizontally in Container – Centers the object horizontally in the view.
- Center Vertically in Container – Centers the object vertically in the view.
- Fill Container Horizontally – Changes the width of the object to the full width of the view.
- Fill Container Vertically – Changes the height of the object to the full height of the view.
The other options in this list box are only available if you have multiple objects selected in the design surface. They allow you to align the objects horizontally or vertically within the containing view.
Springs and Struts in Action
Follow the steps in this section so you can see springs and struts in action. To get the sample code for this tutorial, click on the following link:
- I In Xcode, open the SpringStrutsDemo project in this book’s sample code.
- In the Project Navigator, select the MainStoryboard file. You should see the scene displayed in Figure 8.5.
- Select the Oliver! label at the top of view. Next, make sure that the Size Inspector is selected (click the second button from the right in the Inspectors toolbar). Notice that the label is anchored to the top and left sides of the view and no resizing is selected for the label as shown in Figure 8.4. In fact, all of the user-interface objects on this view have the exact same setting.
- To see how this view looks at run time, press Xcode’s Run button and when the App appears in the Simulator, it will look like Figure 8.6. This is as expected. The view at run time looks just like the view at design time.
- To see how the view looks when the view size changes, let’s rotate the iOS Simulator. To do this, go to the iOS Simulator menu and select Hardware > Rotate Right. The view now looks like Figure 8.7.
- To do this, go back to Xcode and press the Stop button. Next, select the label at the top of the view. In the Size Inspector’s Autosizing setting, click the left strut to remove the anchor on the left side of the view (Figure 8.8).
- Now let’s take a look at the image view. You don’t want the image view to be repositioned when the view size changes. It is currently anchored to the top and left of the view, and that’s a good setting, so we’ll leave it as is.
- Select the text view on the right side of the scene. It’s best to pin this control to the top and right side of the view. To do this, click the left strut to remove the anchor on the left side of the view and then click the right strut to anchor the control to the right side of the view, as shown in Figure 8.9.
- Next, select the Done button at the bottom of the scene. You want the button to be anchored to the bottom of the view, but centered between the left and right sides. To do this, click the top struts to remove these anchors, and then click the bottom strut to anchor the button to the bottom of the view as shown in Figure 8.10.
- To see how these settings work at run time, click Xcode’s Run button to run the App in the iOS Simulator. Then, in the iOS Simulator menu, select Hardware > Rotate Right. The App now has the UI controls positioned properly for both portrait and landscape modes (Figure 8.11).
Figure 8.5 The SpringStrutsDemo scene
At the top of the scene is a label displaying the name of the play, Oliver! Beneath the label is an image view that displays a picture from the play, and on the right of the image view is a text view describing the play. At the bottom of the screen is a Done button, which doesn’t do anything at this point but will be used to demonstrate how autosizing and positioning works with springs and struts.
Figure 8.6 The SpringStrutsDemo App at run time
Figure 8.7 The SpringStrutsDemo App rotated right
As advertised, all of the UI controls maintain their X and Y position coordinates because the autosize settings anchor them to their position relative to the top and left sides of the view.
Not only does this look bad, but the Done button at the bottom of the view is not visible because its Y coordinate places it off the screen. This is obviously not what you want. Let’s change the position settings to more appropriate values.
Figure 8.8 Label anchored to the top of the view
As you can see by the Example animation on the right, since there are no left or right anchors, the label is centered and anchored to the top of the view as the view is resized.
Figure 8.9 The text view is anchored to the top and right sides of the view.
Figure 8.10 The button is anchored to the bottom of the view.
Figure 8.11 The UI controls are placed in much better positions.
As it stands right now, the controls are positioned properly, but we can make improvements by changing the size of the controls.
Currently, all of the controls maintain the same size when moving from portrait to landscape mode. This doesn’t take full advantage of the additional space available. Notice the large white space between the image view and the text view. Also, the width of the label at the top of the scene doesn’t change when moving to landscape, so it isn’t taking full advantage of the extra space that may be needed for longer play titles.
Follow these steps to automatically resize the controls when moving between portrait and landscape modes:
- If the App is still running in the Simulator, go back to Xcode, and press the Stop button.
- Select the label at the top of the scene. Go to the Size Inspector and select the horizontal spring in the middle of the Autosizing control as shown in Figure 8.12. This indicates the width of the label automatically resizes with the width of the view.
- Next, select the image view in the design surface and then, in the Size Inspector, click the horizontal spring to indicate that its width should also automatically resize with the width of the view.
- Select the text view on the right side of the scene and click the horizontal spring to indicate that its width should change with the width of the view.
- You don’t want the button to be resized, so don’t choose any resizing options for it.
- To see how the view looks at run time, press the Run button to run the App in the Simulator. Notice in Figure 8.13 that the image view and text view stretch proportionally to take advantage of the extra width of the screen in landscape mode.
Figure 8.12 The label is set to autosize its width.
Figure 8.13 The image view and text view adjust widths in landscape mode.
This should give you a basic idea of how to use springs and struts to lay out your user interface. As already mentioned, the very nature of expressing layout by means of springs and struts makes this technology very limited in providing all the power you need to lay out your user interface. Ultimately, you often need to write code to position and resize your controls to get your controls to be sized and positioned correctly. In fact, every real App I have ever written required me to write code to fill in the blanks where springs and struts couldn’t do the job.
In Part 2 of this tutorial, you will learn how to use the new iOS 6 Auto Layout to manage the resizing and repositioning of your App’s user interface.