Chapter 22: AutoLayout Size Classes

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.


What you will learn

  • How to use AutoLayout size Classes
  • Implementing device-specific features

Key Terms

  • Size Classes: a way of configuring a user interface with device-specific features.

Resources

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.

Creating a new Xcode project

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".

Figure 3.4.1 Screen Shot 2016-10-22 at 11.31.12 AM.png

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):

Figure 3.4.2 Screen Shot 2016-10-22 at 11.34.12 AM.png

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.

Adding items & constraints to ViewController

Review of AutoLayout

Drag a 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):

Figure 3.4.3

Screen Shot 2016-10-22 at 11.41.27 AM.png

Figure 3.4.4

Screen Shot 2016-10-22 at 11.42.59 AM.png

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.

Using Size Classes in Interface Builder

Click the landscape orientation button at the bottom of the screen to rotate our device in Interface Builder (Figure 3.4.5):

Figure 3.4.5

Screen Shot 2016-10-22 at 12.09.18 PM.png

If you look closely, you will see that now our iPhone has a compact width and compact height (Figure 3.4.6):

Figure 3.4.6

Screen Shot 2016-10-22 at 12.10.41 PM.png

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):

Figure 3.4.7

Screen Shot 2016-10-22 at 12.13.45 PM.png

Now anything that we change will affect the devices and orientations shown in blue (Figure 3.4.8):

Figure 3.4.8

Screen Shot 2016-10-22 at 12.18.58 PM.png

Click on the landscape-oriented iPhone 6s and select the UIView in the ViewController. Make sure that the Size Inspector (Screen Shot 2016-10-22 at 12.22.44 PM.png) 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):

Figure 3.4.9

Screen Shot 2016-10-22 at 12.28.06 PM.png

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 Add Variation.

Figure 3.4.10

Screen Shot 2016-10-22 at 12.29.55 PM.png

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)!

Figure 3.4.11

Screen Shot 2016-10-22 at 12.33.03 PM.png

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): Screen Shot 2016-10-22 at 12.52.59 PM.png

A note about iPad and iPhone 6 Plus

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
iPad Portrait Regular Regular
iPad Landscape Regular Regular
iPhone Portrait Regular Compact
iPhone Landscape Compact Compact
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!

A more useful example

Now that we've used size classes to make changes depending on the screen width, let's make something a little more useful.

Setting up the UI

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):

Figure 3.4.12

Screen Shot 2016-10-22 at 2.31.55 PM.png

Click the Pin button (Screen Shot 2016-10-07 at 8.45.13 PM.png) and give the UITableView the following constraints: Screen Shot 2016-10-22 at 2.33.57 PM.png

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):

Figure 3.4.13

Screen Shot 2016-10-22 at 2.37.51 PM.png

Click on the UIView you just made and click the Pin button (pin-button.png) to give it the following constraints (Figure 3.4.14):

Figure 3.4.14

Screen Shot 2016-10-22 at 2.41.13 PM.png

We pinned it to the top, left, and right sides of our screen and gave it a fixed height of 52.

Modifying the UI for iPad

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):

Figure 3.4.15

Screen Shot 2016-10-22 at 2.47.10 PM.png

To change the height based on the device we're using, click on the Size Inspector (Screen Shot 2016-10-22 at 12.22.44 PM.png) 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). Again, leave 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).

Figure 3.4.16

Screen Shot 2016-10-22 at 2.49.25 PM.png

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:

Figure 3.4.17

Screen Shot 2016-10-22 at 3.17.11 PM.png

Click 'Done Varying' to end changing our variation and then click on the iPhone 6s to switch back to an iPhone screen size.

Adding a label to a UIView

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:

Figure 3.4.18

Screen Shot 2016-10-22 at 3.25.19 PM.png

Next, we need to add some constraints to keep the UILabel where we want it. Click on the UILabel then click the Pin button (pin-button.png) to add the following constraints (Figure 3.4.19):

Figure 3.4.19

Screen Shot 2016-10-22 at 3.30.49 PM.png

Afterward, we need to make sure that our label stays centered. To do this, click the Align button (align-button.png) 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:

Figure 3.4.20

Screen Shot 2016-10-22 at 3.36.04 PM.png

Let's change the font so it is larger on a larger device. Click on the UILabel and ensure that the Attributes Inspector (attributes-inspector.png) 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):

Figure 3.4.21

Screen Shot 2016-10-22 at 3.38.23 PM.png

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):

Figure 3.4.22

Screen Shot 2016-10-22 at 3.46.18 PM.png

Now the font size is much easier to read on an iPad screen:

Before Screen Shot 2016-10-22 at 3.49.02 PM.png

After Screen Shot 2016-10-22 at 3.48.50 PM.png

Showing/Hiding elements on different devices

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):

Figure 3.4.23

Screen Shot 2016-10-22 at 3.56.07 PM.png

Click on the label, click the Pin button (pin-button.png), and add the following constraints (Figure 3.4.24):

Figure 3.4.24

Screen Shot 2016-10-22 at 3.58.27 PM.png

Click the Align button (align-button.png) and add the following constraints (Figure 3.4.25):

Figure 3.4.25

Screen Shot 2016-10-22 at 4.01.21 PM.png

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):

Figure 3.4.26

Screen Shot 2016-10-22 at 4.08.40 PM.png

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.

Figure 3.4.27

Screen Shot 2016-10-22 at 4.13.47 PM.png

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!

Figure 3.4.28

Screen Shot 2016-10-22 at 4.16.02 PM.png

Wrapping up

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.

Exercise

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.