Previously, Apple made only one screen size for the iPhone. Today there are many different sized iPhones and iPads. Moreover, many apps support landscape mode as well.
If you try running the apps you created so far on different simulators, you'll notice that the alignment of your UI objects is different than what you designed. For example, try running your last project on different simulators ranging from iPhone 5s to iPhone 8 plus. You'll often notice objects that are off-center. Sometimes the objects shift left, and sometimes they shift right depending on the size of the iPhone or iPad you're trying to run it in.
Rather than creating different interfaces for each screen size, Apple came up with a system known as auto-layout. Auto Layout is a system of constraints, or UI rules, that govern the size and position of elements on the screen.
Let's see to how use auto-layout to make sure your apps look good on all the devices, regardless of the screen-size.
Let's start by opening a new project, and adding a label to the screen. Give it a background color so that you can make out its boundaries clearly.
On the bottom right corner you'll notice the Add New Constraints menu. This is used to add constraints to our objects. Right next to it, you'll see the Align menu, which is used to create constraints relative to the current or another view. (Hovering on the icons reveals the name).
Click on View as iPhone 8 (at the bottom) to bring up all the other models and choose to see how your interface looks on each of the different interfaces. You'll see your label jumping around.
Broadly, there are two methods we can use for auto-layout — pinning and alignment.
- In pinning, we try to pin the object, i.e. try to assign a position to the object. We do this by defining constraints, such as "Object should be 100px away from the top and bottom", and "Object should be 30px from left and right". So as the screen sizes change (say iPhone 8 vs iPhone 8+) then these constraints remain the same and our object becomes smaller / larger in size. This method is good for objects that need to stretch or shrink as the phone size changes.
- In alignment, the size of the object remains constant, and we align the object from the horizontal and vertical centre of the screen or the view in which the object is placed.
Let's see hot to apply the pinning concept to the UI label we just created.
Click on the UI label and then on Add New Constraints.
Uncheck Constrain to margins. The app has default margins, unchecking this means that the constraints we add will be from the edges of the screen.
If you click on any of the four drop downs at the top, it shows us from which reference we want to pin the label - View and Safe Area. (In general, there may be more options here based on the specific UI object that is selected.) We are going to select the View option, this will give us the constraint from the edge of our screen.
Let's do this for all the 4 sides and click on Add 4 Constraints. (Note that the red dotted lines will become solid, to indicate that you want to add that constraint. You can toggle it by clicking on the red line).
Then, look at what the label looks like on various phones. The black area will stretch to satisfy the constraints from the edges that we just added.
If you used values similar to the above screenshot, the label shape will look quite different on iPhone 8, iPhone X and iPhone 8+. But the distance from the edges will be the same.
You will also notice that when the UI Object is selected the lines are blue. This indicates that no constraints are being violated (those constraints appears in red).
You can remove constraints by clicking on the triangle sign on the right of Add New Constraint.
There are two options to Clear Constraints. One clears the constraints on the selected object and the other clears all the constraints for this view. Make sure you use this appropriately. If you happen to click Clear constraints by mistake, use Cmd + Z to undo.
Now, lets try the alignment method. Recall that in alignment, we want the height and width of the UI object to be the same on every device and positioning is done relative to the center of the view.
To start out, we need to give the label a fixed width and height. To do this, go to Add New Constraints, check the Height and Width boxes and type in appropriate values. Then, click on Add 2 Constraints.
Now, go to the Align menu (on the left of Add New Constraint) — it's the one that looks like two bars. Check Horizontally in Container and Vertically in Container and then do Add 2 Constraints. This sets the label to be in the centre of the screen.
Then, see what the label looks like on iPhone 8 plus, iPhone 8 and iPhone X, and also check the landscape orientation. The size of the label will remain the same, and it will be positioned at the centre of the screen in all the cases.
When defining constraints, it is important to ensure that we haven't added too many or too few constraints.
If we add too many constraints, the app is forced to break some constraints since it cannot satisfy all of them. For example, if we pix the left and right edges to be 15px away from the margin, and the width to be 300px, at-least one constraint will break if the screen-width is not 330px (15 + 15 + 300).
Similarly, if we add too few constraints, the app has the flexibility to place the same object in multiple different ways, and it's going to choose any one of those ways. For example, suppose we fix the distance from the left, right and top margins, but not the bottom. Now, the app can choose the bottom boundary of the UI object as it pleases.
To fix this, we need to specify either a fixed height for the UI Object, or the distance from the bottom margin, or fix the aspect ratio of height to width. Any one of these options work. But we must choose exactly one of these options, since adding more than one will lead to a set of constraints that can't all be satisfied, and the app will choose which one to break.
As a rule of thumb, you should have exactly 4 constraints per UI object (since there are 4 boundaries - top, bottom, left, right).
As an exercise, clear all constraints and create a label which (a) has a fixed height and (b) is at a fixed distance from the top, left and right margins.
When we have multiple UI objects on the screen, we have to carefully devise the set of constraints we will need. We will also need to use the options we have seen so far, and other options which have always been grayed out so far, because they are meant to be used for multiple UI objects.
For example, take a look at the following layout. How would you go about achieving it? (Take a look at the other options available in the Add New Constraint menu and the Align menu.)
A bad way to achieve the above result is to set numeric constraints for of the objects. Suppose, we said each button should have a height of 30px. Now, if we need to make the height 32px for all the buttons, we will need to edit all of them.
Instead, a better way to achieve this is to add constraint for all the buttons being equal height. Then, choose the top or the bottom button as being the "special" one, and give it a specific height. Then, you'll only need to change the "special" buttons height to change the height of all the buttons.
Okay, let's do it.
Add 4 buttons from the Object Library to the storyboard.
Give them a blue background (so that you can see them clearly as you move them around) and white text.
We will use the bottom button as the "special" button. Give it a distance of 20px from the bottom, left and right. And a height of 40px.
We have added all the 4 constraints required for the bottom button. And it is indeed in the correct place and size that we want it to be.
Select all 4 buttons, and give them give them Equal widths and Equal heights and Align their Leading edges (you can also align Trailing Edges or Center, it doesn't really matter in this case since the widths are all equal).
Notice that the total number of constraints is 9. We are adding 3 constraints of each of the 3 types. (Setting 4 objects to have equal heights is 3 constraints, not 4.)
Next, select the top 3 buttons, and set the distance from bottom to the closest object to be 10px.
Checkout the result in multiple different phones - iPhone 8, iPhone 8 plus and iPhone X. Make sure it is what you expected.
In the previous section, we discussed that we should have 4 constraints per UI object. We have 4 UI objects, to the total number of constraints should be 16. We you verify that this is indeed the case — we added 4 + 9 + 3 constraints, which is 16.
One last thing before we move on to the next example. If you look at the Document Outline area (and expand all the items), you will see all the constraints listed.
You can click on individual constraints to edit or delete them. To edit, use the Attribute Inspector. To delete, press the delete key on the keyboard.
To make it easier to understand the constraints, you can also rename the buttons. Select the button in the Document Outline, press Enter, and type in the new name.
Awesome! Play around and explore for a while, and then move on to the 4th and final example for this tutorial.
In this last example, we will use auto-layout to position two images next to each other. To do this, we are going to use an object from the Object Library known as a View.
Positioning each object relative to each other gets tiring and complex very quickly. Often, this also means that the end result might not look like what you wished for.
A View is used as a container in which we can keep other objects together. We can pin or align the object relative to the View, and the View itself is pinned / aligned to the edges of the screen (or other views).
You can even use a view to cover the entire screen and position all the views and objects inside the parent view. This makes the app look the same on all phones and screen sizes.
Go to the Object Library and search for View. We want a View, whose icon is a white box in a grey background. Add the View to the storyboard.
In your Document Outline you can see the View object. When we are dealing with multiple views it's better to name them. To change the name, click on it and press Enter. Rename the View to middle container.
Our middle container will contain two images. To add an image onto the app, go to the navigator where all your project files are there and click on the folder Assets.xcassets. Over here, drag and drop an image under AppIcon. Go to the Attribute Inspector of the image and give it an appropriate name and press Enter.
Then, go back to Main.storyboard, search for Image View in the Object Library and drag it onto the View (middle container). Change the background color of our view so that you can see it on the screen at all times. As you place and resize the Image View, try to keep it touching the border of the View and go outside.
Then, click on the Image View and go to the Attribute Inspector. You will see an image option. Click on the dropdown menu, and you will be able to find the image you added in the Assets folder.
Do the same thing for another image and place both the images on extreme ends of the view.
You screen should look similar to above. If you look over onto the Document Outline, you will see the images placed inside the container which is what we want. (If not, then move it inside the middle container). You can rename these images in the same way.
Now in the Document Outline, select middle container. Go to Add New Constraint and fix its Height and Width. Then go the Align and position it at the center.
Next, we want to add constraints for the images so that they are located at the ends on either side of the middle container.
Click on an image and go to Add New Constraint. Fix its Width, and pin it to the edge of the View. For right image, pin it only to the right (as the distance between the two images can vary and we don't want to pin that).
Similarly, add constraints for the image on the left.
Try viewing this in other devices and orientation, you'll see it looks the same. Play around it with for a while before moving on.
Great job! This was a tricky lesson. You learn about
- Pinning and Alignment - the two main strategies to use with auto-layout. Pinning focuses on fixed position, and alignment focuses on fixed size.
- Auto-layout for multiple UI objects - you saw two examples. One where you used relative constraints to place 4 buttons. And another where we used a View and placed our UI objects inside the View.
As an exercise, use auto-layout on the previous project and check that the app looks good on different phones.