This workshop will be retired on May 31, 2020.
Frame Based Layouts16:14 with Pasan Premaratne
Prior to Auto Layout and the introduction of multi-sized iOS devices, laying out the user interface was relatively simple. Before we start exploring Auto Layout, it's worth understanding how views were positioned and sized by iOS and why the old ways of doing this aren't as straightforward anymore.
[MUSIC] 0:00 Hi, my name is Pasan, and I am an iOS developer. 0:04 Over the next few videos, we're going to spend some time getting 0:08 familiar with the basics of Auto Layout, the primary positioning, 0:12 and sizing mechanism for iOS, Watch OS, TV OS, and Mac OS apps. 0:17 When Auto Layout was first released, there was a lot of frustration and 0:22 apprehension around it. 0:25 Why did developers have to move from a system that worked perfectly at the time? 0:27 Why was Auto Layout so confusing? 0:32 And why did it rarely ever work beyond the simplest of used cases? 0:34 Auto Layout has come a long way since its release, and 0:38 is now a much more robust system with better Xcode support. 0:42 Many developers are still skeptical having been burned by their initial experiences. 0:45 Over a series of videos, we hope to dispel all those feelings and 0:51 get you comfortable with using Auto Layout. 0:55 We're going to start all the way from the beginning with a history lesson 0:58 to help understand some of the motivations behind Auto Layout, and 1:01 then we'll work our way up. 1:05 We won't cover the entirety of Auto Layout here as there's a lot of ground to cover, 1:07 but I linked the relevant content where you can learn more. 1:12 Now, before we start with actual Auto Layout, 1:15 I'd like to give you an idea of why Auto Layout 1:18 is absolutely the way you should be sizing and positioning your views. 1:21 Hopefully, this isn't as relevant anymore. 1:25 But in the recent past, if you Googled Auto Layout tutorials, you would, and 1:28 you still may encounter a lot of people complaining about it, and 1:32 that might effect your mindset from the get-go. 1:36 But understanding why the old way isn't going to cut it anymore 1:39 will be a lot more appreciative of Auto Layout going forward. 1:43 Let's start by creating a brand new Xcode project. 1:47 I should note that all this content is written at the time of Xcode 9 and iOS 11. 1:50 If you're watching this in the future, 1:56 then look in the teacher's note section for any updates or changes. 1:58 We're going to build a really simple layout without Auto Layout 2:02 to get a frame of reference. 2:07 Pun intended, if you know what I'm talking about. 2:08 So we'll create a new single view app, and I'm going to call this, 2:11 Springs, AndStruts, 2:14 and we'll hit Create. 2:19 In Main.storyboard, in our storyboard scene, 2:24 we're going to click on the file inspector in the utility's panel. 2:27 This is the first icon from the left. 2:31 Now, if we scroll down, there is a section. 2:34 Make sure we're in our scene. 2:37 Okay, and then we get the contextual menu here. 2:39 And if you scroll down, you'll see the section, Interface Builder Document. 2:42 We're going to uncheck the box that says, Use Auto Layout. 2:47 The moment you do this, you should see a pop-up asking you to disable a feature 2:51 known as trait variations, and create a document that limits you to designing for 2:54 a single device family, like the iPhone, 2:59 instead of universal layout that targets the iPhone and the iPad. 3:02 Now, in addition, if you read the fine print, 3:06 you'll see that this affects how we use segues as well. 3:08 They are no longer adaptive. 3:12 So this should be your first indication of the flexibility that Auto Layout offers. 3:15 Okay, so we'll Disable Trait Variations. 3:20 Without Auto Layout, we have to create different layout documents for 3:23 varying device sizes. 3:27 Right now, we're designing for the 4.7 inch iPhone, 3:29 which at the time of this recording, is the iPhone 8. 3:32 If you look at the very bottom of the Xcode window, inside of the storyboard 3:37 scene or inside of the storyboard editor, you'll see a menu down here. 3:42 Now, this is the document outline. 3:46 So this down here is the menu I'm talking about. 3:48 Right now, over here on the left side of the menu, it says, View as iPhone 8. 3:51 There's some other symbols there, WCHR. 3:57 We're gonna ignore those for now. 4:00 So you can click on these. 4:02 And as you can see, you can change the device we're designing for. 4:03 This is a canvas for the iPhone 10. 4:08 And you can also change the orientation. 4:11 We're going to keep it at the 4.7 inch iPhone, or the iPhone 8. 4:14 Our design here is going to be very simple. 4:18 So we're going to drag a view onto the scene from the object library, 4:23 gonna place it in the middle. 4:28 And let's give it a different background color. 4:31 So we'll select the view, and then we'll go to the attributes inspector. 4:33 And under Background, let's change it to something random, so 4:36 that we can differentiate it. 4:39 Now, let's position and size this view using the Size Inspector, 4:41 which is the second icon from the right in the utilities area. 4:46 Okay, so we're going to give this an X value of 25, a Y value of 44. 4:52 So that puts it up there a little, okay? 4:58 We're going to give this a width of 160, and a height of 300. 5:01 Now, our four different views. 5:07 So I'm going to select this hit commands C to copy, 5:08 and then I'm going to paste it three times. 5:12 Let's space them out, so they look a bit like this, and 5:15 then let's modify these values. 5:19 So the next X value, we're going to say is at 191, Y 44. 5:22 And then this one, the bottom left is at X 25, 5:28 Y 352, oops, messed with the wrong things, 5:34 X 25, Y 352, okay? 5:40 And the last one is at X 191, Y 352. 5:43 Let's go ahead and give each of these different background colors. 5:49 Well, it doesn't matter what you pick. 5:52 So we'll just go ahead and 5:53 pick some recently used colors here, and gray. 5:56 And then let's hit Other, and we'll get a blue. 6:02 Let's pretend we're back in 2008. 6:09 There's only one iPhone to make apps for. 6:11 So by positioning a view like this, using a hard-coded coordinate point, 6:14 we don't need to worry about other layouts in portrait. 6:18 What you see here is where the final view is positioned. 6:22 Now, making sure you select iPhone 8 from the simulator menu or 6:25 the simulator options. 6:30 Let's run this app. 6:31 Now, when the simulator comes up, 6:33 you might have to resize that a bit to fit on the screen. 6:35 There we go. 6:40 And as you can see, the layout is pretty much identical. 6:41 So back in the day, you didn't really have to worry about your layout changing in 6:45 portrait mode, because you only had a single device to worry about. 6:49 Okay, well, what if the user rotated their phone? 6:53 Now, you can rotate the simulator by using the command and arrow keys. 6:56 And when you do this, you'll see that the layout breaks immediately. 7:00 So, what do we do here? 7:03 Because iPhone rotation was initially the only layout and 7:05 sizing problem we had to worry about on iOS, the solution was relatively simple. 7:09 Every view has an autoresizing mask property that determines 7:15 how that view should behave when the containing view is resized. 7:19 When we rotate the phone, the container view, 7:23 the view that these four views are embedded in, changes its size. 7:26 And using autoresizing tasks, we can dictate how any subviews respond. 7:31 So back in our scene, let's clear out all this, okay? 7:36 Let's select this first view. 7:40 And again, we're going to go back to the Size Inspector. 7:41 Now, the third section here labeled Autoresizing is what we're concerned with. 7:45 An Autoresizing mask consists of two components. 7:51 Fixed offsets from the superview, 7:55 which are represented by the I-bars that you see here. 7:58 And then flexible sizing allowances within the view, 8:03 represented by these arrows inside the box. 8:06 This autosizing solution was commonly referred to as springs and struts. 8:09 Where springs refer to the flexible width allowance, 8:15 while struts were the components that kept the views a fixed offset away. 8:18 With springs and struts, we're essentially saying we want a view to be a fixed offset 8:23 away in a certain direction. 8:28 So take the first view. 8:29 When we rotate the phone, we always want this red color view to be the top left. 8:32 So in the Autoresizing section, we can specify that this view is always 8:37 a fixed offset away from the top left by making sure these two I-bars are selected. 8:43 We'll repeat this to specify an offset for all the other views as well. 8:49 So, for the second view, for the green view, 8:53 we need to be offset and pinned, sort of, to the top and right. 8:56 Deselect this one. 9:01 And then the gray one is left and bottom. 9:02 And then finally the blue one is right and bottom. 9:07 So we'll disable these. 9:10 And you could see here what that looks like. 9:12 Okay, now, if we stop and run the app again. 9:15 So our portrait layout should look the same, nothing changes there. 9:19 And when we rotate, okay, our layout looks somewhat better, but 9:23 the spacing isn't what we specified. 9:27 So, let me do it in this direction. 9:30 So they're pinned to where we want to, but they're sized differently, and 9:33 there's some spacing issues. 9:37 There's no spacing between the views in the Y direction. 9:39 But in the X direction, horizontally, there's this ton of space. 9:42 So the issue here with Autoresizing masks is that you can tell the views how to 9:46 resize or how to react, but not by how much. 9:51 Okay, so let's hit stop, and we'll go back again and 9:55 get rid of the Autoresizing masks that we put on, Right? 9:58 So deselect all of them. 10:05 And what we're gonna do instead is create outlets, For each of these views. 10:11 Right, so we had the Control drag over, 10:21 and I'll say redView, 10:26 greenView, keep the naming simple. 10:33 GreyView, is that how you spell grey? 10:40 I always forget, and blueView. 10:44 Okay, now instead of using Autoresizing masks, we're going to position and 10:48 size these views in the view will layout subviews method. 10:53 I'm going to go back to the standard editor and 10:57 navigate to the ViewController, since that's where we're adding our code. 11:00 And in here, we'll add that method in, so it's called viewWillLayoutSubviews. 11:05 And we'll first call super. 11:12 Okay, since we want to alter our layout when we switch orientations, 11:14 we're going to detect if we're in landscape and switch our layouts. 11:20 We can get the orientation of the current device by writing let orientation 11:24 = UIDevice.current.orientation. 11:30 This returns an enum with a series of values that describes orientation. 11:35 So we want to check if its either UI device orientation dot landscape left, or 11:40 dot landscape right, and then alter our layout. 11:44 So we say, if orientation == .landscapeLeft, 11:47 or orientation == .landscapeRight, then we'll change our layout. 11:52 So now is where we write a lot of repetitive code. 12:00 For each view, we're going to modify the view's current frame rectangle. 12:03 So we'll say redView, or, right, that's our first one. 12:07 So I say, redView = CGRect. 12:10 So I'll say redView.frame. 12:17 Since the frame is a rectangle, 12:20 we'll define a new rectangle to occupy a size and position. 12:22 In here, we'll say x: 20, y: 20, width is 307, height is 161.5. 12:26 The next one is the greenView's frame. 12:33 And again, we'll pass in a new rectangle. 12:37 And this one is x: 340, y: 20, 12:40 width: 307, height: 161.5. 12:45 Next is the greyView. 12:50 And we can copy-paste this. 12:56 The x value here is 20, y is 193, and the width and the height are the same. 13:00 And then finally, we have the blueView.frame =, 13:07 and we'll paste this again. 13:12 And finally, the only values we have to change here is the y value, so y: 193. 13:15 Okay, let's run this again. 13:21 So if you run the app in, hold on. 13:26 We'll make sure you run it in portrait, there we go. 13:31 Now, if you run the app here in the original portrait orientation, 13:33 it looks okay. 13:36 This is what we specified. 13:37 And then if you rotate the app, 13:38 you can see that we've managed to maintain the layout. 13:40 But if we rotate, again, back to portrait, you'll see that it's broken. 13:43 So to fix this, we need to add an else clause to our layout code. 13:49 So we'll say else over here, and then we're going to copy all of this, 13:54 paste it, and again, change the values. 13:59 So x: 25, y: 44, 14:03 width: 160, height: 300. 14:07 Again, I'm going to copy-paste this frame. 14:14 And then for the greenView's frame, I'll paste this here. 14:18 The x value is 191, y is 44, width and height are the same. 14:21 So this is for the greyView. 14:27 The x value is 25, y is 348, and then everything else is the same. 14:31 And finally for the blueView, x, oops, scroll back up. 14:37 x is 191, y is 348, and everything else is the same. 14:43 So now, again, if we run our app and rotate the phone, 14:50 we can keep rotating, and everything works okay, right? 14:54 Actually, not really. 14:59 So let's hit stop, and we'll switch the simulator over to the iPhone 8 Plus. 15:01 Or better yet, let's do it to a 5S, 15:07 which is the smallest screen size that we have available with this version of Xcode. 15:09 So on an 8 Plus, if you run it, and 15:15 you can try it first, you'll see that there's lots of white space. 15:18 But on the 5S, which I'll need to resize, once this loads, 15:22 you'll see that the views don't even fit on screen. 15:28 So if we want to do this the old way using springs, struts, or 15:31 manually setting view coordinates, we need to have of 15:35 if else clauses to catch each device size and orientation. 15:40 While the old way of laying out views does get the job done, 15:46 we'd have to write a lot of code to achieve it. 15:50 At the time of this writing, there are five different iPhone screen sizes we need 15:53 to support with just ten layouts, if we include orientation changes, and 15:57 none of that includes iPads for universal apps. 16:02 So hard coding coordinate points is simply not a feasible approach. 16:06 So that's the old way. 16:10 Let's see what Auto Layout brings to the table. 16:12
You need to sign up for Treehouse in order to download course files.Sign up