This workshop will be retired on May 31, 2020.
Intrinsic Content Size, Content Hugging and Compression Resistance12:56 with Pasan Premaratne
Views that have content already have a predetermined size and Auto Layout can use this to manipulate the view's frame. How it achieves this depends on two additional properties. In this video, let's take a look at content compression resistance and content hugging.
For this video, we're gonna jump right in. 0:00 So let's add a new storyboard to our file, gonna drag this previous one up. 0:02 Right click new, and we're going to call this one intrinsicContentSize. 0:07 Okay, as always, we'll start off by adding a View Controller in here 0:19 marking it as initial, and then proceeding to put some views in here. 0:24 So we're going to drag a Label out from the object library, and 0:29 place it in the scene anywhere, it doesn't really matter, and I'll zoom in here. 0:34 And next from the autolayout pin menu, so the second icon from the right. 0:39 Let's add a top and leaving space constraint. 0:46 So for the top one, we'll say 32 points, and for the leading space we'll say, 0:48 16 points, Add 2 Constraints. 0:53 When learning about the basics, I told you that to satisfy autolayout, we needed to 0:57 provide at minimum four constraints, two in each axis for position and for size. 1:02 Now, contrary to that statement, after adding just two constraints here 1:10 to the label, autolayout can determine the position and size. 1:14 And you might have noticed this before. 1:18 We know this because we can see the blue I bars that indicate a layout solution. 1:21 This happens because of a property known as intrinsic content size. 1:26 View subclasses, like labels that contain content, can determine its size, 1:32 that is, its height and width, based on the content that we add to it. 1:38 This size is dynamic and determined at runtime. 1:43 So things like font sizes, string attributes, and 1:47 dynamic type all affect the intrinsic content size of the view. 1:49 When autolayout works with view subclasses that have an intrinsic content size, 1:54 it can determine the size that the view needs to be. 2:00 And it adds complicit constraints to the view to size it. 2:03 This means that we only need to worry about the position of the view. 2:07 And we add two constraints, one in each axis, and that suffices. 2:11 Now it's important to know that not every view has an intrinsic content size. 2:16 The keyword here is content, only views that contain some kind of content 2:20 will have an intrinsic content size. 2:25 Labels and buttons have an intrinsic content size since they contained texts. 2:28 Image views have an intrinsic content size since they contained an image 2:34 with dimensions. 2:38 While this is useful, there are some tricky aspects of relying 2:40 on the intrinsic content size to determine the end result. 2:43 So let's add two more labels to the scene. 2:47 We'll set the text on the second label here to a long label. 2:52 And then the last one we'll say, an even longer label. 2:58 Let's position these labels. 3:05 So we'll align the top edge of both of the labels with the top edge of the first one. 3:07 Now this is easier with the Ctrl+Drag model. 3:12 So if we select one of the labels, hold the Control and 3:14 drag over, we can say top to align the tops, and we'll do this here as well. 3:18 And then after that, we'll simply set some horizontal spacing constraints. 3:24 So here, we'll go to the pin menu, and we'll say, 3:29 we want this to be 16 points from the first level. 3:33 Now remember when I talked about the pin menu at the very beginning? 3:37 I said that both the advantage and disadvantage is that when you do it this 3:41 way using the pin menu, all you specify is the type of constraint. 3:46 So here this is a leading and the space so the constant value, which here is 16. 3:50 I'm not actually specifying that I want it to be in relation to the first label. 3:54 But that's okay because this pin menu 4:00 simply selects the nearest neighbor which happens to be this label. 4:03 So there might be a bit of confusion if there's a bunch of views and 4:07 you need to pin to a very specific one. 4:11 And in that case, you would use a Ctrl+drag model. 4:13 But in most cases, this works, we'll add this constraint and 4:15 then we'll do that again here. 4:20 Let me do that using the pin menu, And 4:22 we'll set this to 16, all right, and then hit Add Constraint. 4:25 Okay, so now if your frames didn't update, you can click on the Update Frames button, 4:31 which is the very last button from the right, or the first from the left. 4:36 Now all the labels should be in place. 4:41 Now that we have an initial layout, let's change the text of the first one to, 4:43 The first label. 4:50 Because the size the of the label is determined by the content 4:54 as we add more text to the label, the implicit with constraint added by 4:57 autolayout now has a larger constant value. 5:01 This causes the second and third labels, 5:05 who's x position is relative to the width of the first label to move rightwards. 5:07 And this is fine, this is what we expected but now the third label is off the screen. 5:13 And that's not going to work. 5:19 So let's add another constraint, we're going to select the third label and 5:20 then go to the pin menu. 5:24 And we'll select a trailing space constraint here with a constant 5:26 value of 16 points. 5:31 When we do this, we're going to get red I bars in the horizontal axis 5:34 indicating that we have layout errors. 5:37 With the widths of the labels and the spacing constraints between them, 5:40 there's no way to fit these labels on screen. 5:44 You might say, well just adjust the text of the labels to fit and well, 5:47 we can do that for our example here. 5:51 But in an actual app that get say data from the web, 5:53 we have no predetermined knowledge of the amount of content our labels will hold. 5:56 In cases like this, 6:01 we need to figure out how to accommodate all of the content on screen. 6:03 Now it's important to point out that autolayout considers content very 6:07 important. 6:11 And it will do everything it can to show as much content it can in a view. 6:12 In this case, as you can see here, it's telling us that this layout is impossible 6:18 rather than doing something like truncating a label or 6:23 just hiding one altogether because content is paramount. 6:26 Now to fix this, we, the developer, have to make some choices. 6:30 We need to determine which content is more important than the others. 6:34 In this example, when content is larger than the available space, 6:39 we can truncate it by clipping off the end of the text in the label. 6:43 But how do we indicate this? 6:47 How do I say here that I want the system to truncate the text in the third label 6:49 in the event that the first label grows too wide. 6:54 For that, we have two new concepts, content hugging priority and 6:58 content compression resistance priority. 7:03 Content hugging priority defines how much the view is drawn in by the content. 7:07 When a view has a high content priority, if you try to size it larger 7:13 than it's intrinsic content size, the view will resist. 7:18 In Apple's words, content hugging pulls the view inward so 7:22 that it fits snugly around the content. 7:26 Compression resistance priority, on the other hand, is the force pulling the view 7:29 outwards so that it fits as much of the content as possible. 7:34 With a high compression resistance priority value as the space around 7:38 the view shrinks, the view resists as much as possible to shrink itself and end 7:43 up clipping the content, which is what is happening with the third label over here. 7:48 So on the right edge, we're running out of space, but because of that compression 7:52 resistance, the label is preventing itself from being truncated. 7:57 Now these are tricky concepts and honestly, 8:02 the name doesn't make them easy to remember. 8:05 Apple describes compression resistance priority as the force pushing the view 8:09 outwards, but it does not clip the content. 8:13 A somewhat easy way to remember is that hugging talks about not wanting to grow, 8:17 while resistance means not wanting to shrink. 8:23 Do not worry if you cannot remember these concepts, I don't, 8:27 I have to look them up nearly every time. 8:30 And a lot of developers basically have like diagrams or 8:33 cheat sheets that they post up on the desktop or 8:36 on their actual wall beside their computers so that they remember this. 8:39 Okay, so how do we use these concepts? 8:43 Back in our storyboard here, we'll make some general rules. 8:46 The first label is pretty important to us. 8:49 So when the content increases, and 8:51 thereby the width, we're going to let this label expand. 8:53 On the flip side, the third label isn't as important to us. 8:57 So when the first label grows, we'll force the third label to shrink and 9:01 truncate the content. 9:05 You can think of this, if you want an example to think about, 9:06 let's say this is the iTunes app. 9:10 This might be the movie title, this might be the genre, 9:13 and this might be the release date. 9:15 So we want as much of the title to fit but we don't care if the genre disappears. 9:19 Okay, so the third label not as important. 9:23 So when the first label grows, we'll force the third label to shrink and 9:26 truncate the content. 9:29 To allow the first label to grow, it's kind of counterintuitive but 9:31 rather than messing with the first label, we're going to tweak values on the third. 9:34 To allow the first label to grow, 9:39 we're going to tell autolayout that it's okay to shrink the third. 9:41 So switching over to the third label, 9:45 we need to tweak the content compression resistance priority values 9:48 which can be found in the label's size inspector at the very bottom. 9:52 Just like constraint priorities, 9:57 there are default values defined for this priorities. 9:59 So content hugging and content compression, 10:03 both if you select on the drop-down have required height, medium, and low values. 10:06 Remember that content compression resistance 10:11 translates to how much the views don't want to shrink. 10:14 Higher values means the view tries to prevent autolayout 10:18 from shrinking it as much as possible. 10:21 Since we do want it to shrink, we're going to set a low value. 10:24 As you may have seen, both content hugging and content compression resistance 10:27 specify priority values into vertical and horizontal axis. 10:33 So we could say something like we don't want it to shrink horizontally, 10:37 but we're okay with it shrinking vertically, for example. 10:40 And that may be useful for a multiline label. 10:44 Since we're concerned with how these labels fit horizontally, 10:47 we're going to lower the priority values. 10:51 Now the current value is 750. 10:53 And if you click on the first and second labels, 10:55 you'll see that they're 750 as well. 10:58 It is very important to note that these priority values for content hugging and 11:02 content compression resistance do not exist in a vacuum. 11:07 Like constraint priorities, autolayout takes into account the content hugging and 11:11 compression resistance priorities of any of the surrounding views that effect our 11:17 given view when it's modifying the layout. 11:21 This means that when deciding on a low compression resistance priority value, 11:24 all it needs to be is lower than the values of the first and 11:30 the second since their size affects the third label. 11:33 So it doesn't need to be super low. 11:37 Lower than the others doesn't mean a drastically lower value. 11:40 And in fact, if you click here, and simply change this to one point lower, 11:43 to 749, that fixes our layout. 11:47 Autolayout now knows that this view is less resistant to compression 11:51 compared to any other views in this layout hierarchy, so shrinks the label and 11:56 truncates the content to fit the first label. 12:01 Now if we increase the text in the first label so I can go back to the attributes 12:04 inspector go up, the first label is and then getting. 12:08 As you can see, the more text I keep adding, the third label is going to just 12:14 keep shrinking to accommodate all of this content. 12:18 In addition to the constraints we've learned about, intrinsic content size, 12:22 content hugging and content compression resistance priority 12:26 affect how views with content are positioned and sized by the system. 12:30 This, as always, was only an overview. 12:35 So before you move on to the next topic, 12:37 make sure to work through any of the related cookbook videos. 12:39 Content compression resistance and 12:43 hugging priority are tricky to understand correctly. 12:44 Again, honestly, I look up the definition every single time, so 12:48 do not worry if this doesn't stick. 12:51 Having a reference is all you need. 12:54
You need to sign up for Treehouse in order to download course files.Sign up