AutoLayout is already an incredibly helpful tool in developing iOS apps, but the ability to use Size Classes will make it even more helpful for you as a developer.
Download here: https://github.com/devslopes/book-assets/wiki
AutoLayout in Xcode is an amazing tool in regards to building apps that look beautiful on all screen sizes, but we can customize AutoLayout using size classes to make specific changes or UI decisions based on the screen size. Some things that look great on iPhone don't always look as great on an iPad (seriously, check out the Twitter app for iPad 😁), but size classes allow us to fix this.
To begin, open up Xcode and double-click
Single View Application to create a new project. Name it something like
AutoLayoutSizeClasses and save it anywhere.
Next, open up
Main.storyboard and click on
View as: iPhone xx (wC hR) (Figure 3.4.1) at the bottom of the window.
wC means "Width: Compact" and
hR means "Height: Regular".
Note that the initial device loaded in Xcode is an iPhone 6s in Portrait mode which has a width skinner than it's height – therefore it's width is compact. It's height is considered "regular" because it is in Portrait orientation. If we rotated the device, it's height would then be compact.
What you will see pop up at the bottom of the window are the different screen sizes an iOS device can have (Figure 3.4.2):
We will talk about these in a moment, but for now let's place some things on our ViewController so we can later modify them for different screen sizes.
UIView onto your ViewController into the top left corner (Figure 3.4.3), set a custom background color, Click the Pin button (Screen Shot 2016-10-07 at 8.45.13 PM.png) and give it the following constraints (Figure 3.4.4):
Now, if you click on one of the device options at the bottom, you can see what it looks like on different screen sizes. In Xcode 7, you used to have to go to the Assistant Editor and use the Preview feature to see differing screen sizes. In Xcode 8, you no longer need to do that. What you see in Interface Builder is what you get in the Simulator.
Click through the different screen sizes and see that our purple view maintains the same size and position.
Using AutoLayout is nothing new at this point in the book, but we needed to set up an example for using size classes. Let's do that now.
Click the landscape orientation button at the bottom of the screen to rotate our device in Interface Builder (Figure 3.4.5):
If you look closely, you will see that now our iPhone has a compact width and compact height (Figure 3.4.6):
We will use size classes to change our UIView based on the width of the device. Click the
Vary for Traits button and tick the
Width box (Figure 3.4.7):
Now anything that we change will affect the devices and orientations shown in blue (Figure 3.4.8):
Click on the landscape-oriented iPhone 6s and select the UIView in the ViewController. Make sure that the Size Inspector () is selected and double-click on the
Width Equals: constraint to edit it.
You now should be able to see a list of properties all relating to our width constraint (Figure 3.4.9):
There is a little plus sign (+) next to the 'Constant' property. We want to change this value so that our UIView will be wider when the screen is wider. Click the plus sign and set both the width and height drop-downs to be 'Compact' (Figure 3.4.10). Leave 'Gamut' alone as we don't need to change that. Click
Now we have two 'Constant' properties that we can modify. One is named 'wC hC' and affects our UIView only when it's width and height are both compact. The other is just named 'Constant' and affects it in every other circumstance. Change the value of 'wC hC' from 128 to 300. See how it changes in Interface Builder (Figure 3.4.11)!
Here is where the magic happens... 🔮 Click on the Portrait-oriented iPhone at the bottom of the window. Notice that the UIView is back in it's original form of being a square. Why the change?
Well, the iPhone now has a compact width and regular height. We have it set to stretch to a width of 300 only when both the width and height are compact! So cool! 😎
To finish up this example, click 'Done Varying' on the blue Size Class menu at the bottom of the window):
If you were to switch devices to an iPad, you probably noticed that the height and width are both regular. The iPhone 6 Plus is different in landscape mode than any other iPhone because it has a bigger screen size.
Here is a helpful table to help you remember it all:
|Vertical Size Class||Horizontal Size Class|
|iPhone 6 Plus Landscape||Compact||Regular|
These devices can sometimes cause headaches when trying to get your UI to look nice on both iPad and iPhone. Knowing what size classes to use is definitely a step in the right direction!
Now that we've used size classes to make changes depending on the screen width, let's make something a little more useful.
Select and delete the UIView that we've been modifying so that we have a blank ViewController once again. Drag on a UITableView and position it so that it fits in the ViewController like so (Figure 3.4.12):
Pin button () and give the UITableView the following constraints:
Drag in a UITableViewCell so that we aren't just looking at a grey box that says 'Table View' and afterward drag on a UIView to act as a banner bar at the top of our app. Give it a background color to set it apart from the UITableView. (Figure 3.4.13):
Click on the UIView you just made and click the
Pin button () to give it the following constraints (Figure 3.4.14):
We pinned it to the top, left, and right sides of our screen and gave it a fixed height of 52.
Our banner's height is great for an iPhone-sized device, but on an iPad it looks a bit too skinny (you can check if you want by clicking on the iPad at the bottom of the screen). Let's make it so that when we're using an iPad, the banner is a bit taller.
Click on the UIView banner, then click
Vary for Traits at the bottom of the Xcode window. We want to introduce variations based on height, so tick the 'Height' box (Figure 3.4.15):
To change the height based on the device we're using, click on the Size Inspector () in the top right-hand side of the Xcode window and double-click on our
Height Equals: constraint.
Just like before, we're going to click the plus sign button (
+) next to the
Constant property and on the following pop-up, select
Regular for both height and width (Figure 3.4.16).
Gamut alone. Click
Add Variation and notice how there is a new field beneath
Constant where we can customize the height of our UIView as the device we're using has a regular height and width (i.e. iPads of all shapes and sizes).
Set the value of the
wR hR field to be something taller than 52, like 100. Press
Enter to set that value. Next, click on one of the iPads at the bottom of the screen and see if the height of our UIView changes.
Alas! It works! Your iPad view in Interface Builder should look similar to mine in Figure 3.4.17:
Click 'Done Varying' to end changing our variation and then click on the iPhone 6s to switch back to an iPhone screen size.
Drag on a UILabel and position it at the top and in the center of our colorful banner UIView at the top of our screen (Figure 3.4.18). I gave mine a custom font and set the label to be centered:
Next, we need to add some constraints to keep the UILabel where we want it. Click on the
UILabel then click the
Pin button () to add the following constraints (Figure 3.4.19):
Afterward, we need to make sure that our label stays centered. To do this, click the
Align button () and tick the 'Horizontally in Container' box. Click 'Add 1 Constraint'.
Now our label is staying put. But what if on iPad, we wanted the font size to be bigger. It looks pretty silly at the moment being so small. See what I mean in Figure 3.4.20:
Let's change the font so it is larger on a larger device. Click on the UILabel and ensure that the Attributes Inspector () is selected.
To change the font size on iPad, we don't even need to click the 'Vary for Traits' button but instead we can click the plus sign (+) to the left of the 'Font' property in Xcode (Figure 3.4.21):
On the pop-up, choose 'Regular' for both width and height. Leave 'Gamut' alone again. Click 'Add Variation' to add our font variation.
Now, we see a duplicate font selector beneath the standard one named
wR hR meaning "Width: Regular" and "Height: Regular". If we change the font size on
wR hR, it will only affect iPad. Try it out and bump the font size up to 30 (Figure 3.4.22):
Now the font size is much easier to read on an iPad screen:
Another cool thing we can do is create a label for some subtitle text beneath our app name 'True Blue' and have it show up on iPad but leave it out of the iPhone interface.
To do this click on the iPad in the Device menu at the bottom of the window. Drag on a UILabel beneath the other label already on the screen. Position it like so (Figure 3.4.23):
Click on the label, click the
Pin button (), and add the following constraints (Figure 3.4.24):
Align button () and add the following constraints (Figure 3.4.25):
Now, this looks fine and dandy on an iPad, but what does it look like on an iPhone? Click on an iPhone model in the Device menu to check (Figure 3.4.26):
Yikes. That's not what we're looking for. We need to set our label to show on iPad only, so click on an iPad in the device menu again. Then click on the subtitle label if it isn't selected anymore.
In the Attributes Inspector, scroll down to the very bottom. You should see a tick-box named 'Installed'. Click the plus sign (+) to add a variation for regular height and regular width just like before.
You should now see two tick-boxes – both labeled 'Installed' but one with an extra label saying
wR hR. Leave that box ticked, but untick the default box (Figure 3.4.27). This is basically saying that we want this label only to show on iPads, but everywhere else it shouldn't even be loaded.
Let's go check to see if the subtitle label has been removed from our iPhone. Click on any iPhone from the Device menu at the bottom of the window. You should see the same result as Figure 3.4.28 which means that it worked!
This chapter contained a few basic examples of how size classes work together with AutoLayout to make building user interfaces for multiple devices and screen sizes even easier. We learned how to make changes to our UI determined by screen height or width. We showed a subtitle label on iPads but not on iPhone screens. We made our banner talled on iPad screens as well.
Being able to make our UI this flexible is a very powerful advantage Apple has over other platforms of development. I'm sure you can see how useful this could be when designing full-fledged apps.
The best apps are made by developers who are attentive to detail and care about how the app is experienced on iPhone and iPad. If you're able to make an app that tailors to both devices, your app will be way ahead of many other apps out there now.
Extend this app by adding a
+ button to the upper right-hand corner of our app as if we were to add a post or image to our imaginary app. Give it some constraints to keep it in place. Switch to an iPad in Interface Builder and add in some more buttons to the left of the
+ button. Set them so that they are only installed on an iPad device with a regular height and regular width.