跳转至

8 Content-Hugging & Compression-Resistance Priorities

The content-hugging and compression-resistance priorities (CHCR priorities) define how a view behaves when constraints that are anchored to it attempt to make the view smaller or larger than its intrinsic size. The content-hugging priority represents the resistance a view has to grow larger than its intrinsic content size. Conversely, the compression-resistance priority represents the resistance a view has to shrink beyond its intrinsic content size. To better understand these concepts, look at the following image:

img

Although the image only shows the priorities for the horizontal axis, you can set content-hugging and compression-resistance priorities for both the horizontal and vertical axes. In other words, there are four priorities for every view.

Intrinsic Size and Priorities

Some views have a natural size, which is usually determined by their content and margin. For example, when you use a UITextField, it includes a default height. This height is determined by the font size plus the margin between the text and its borders; this is all part of the intrinsic content size of the UITextField. Other examples of views that size automatically are images, labels and buttons, where their size is based on their content.

When a view has an intrinsic size, the Auto Layout system creates constraints on your behalf, making the size equal to its intrinsic size. This is great when the default size works for your design. It even saves you time because you don’t have to set the width and height constraints for these views manually. However, if you don’t want the view’s size to equal the intrinsic size, you can set the content-hugging and compression-resistance priorities.

Try to use intrinsic content size when possible, but be sure to set the priorities accordingly. These are some of the benefits of doing this:

  • You’ll save time because you need fewer constraints since some of them are automatically given by the intrinsic content size.
  • By using the right priorities, you can make any view grow dynamically depending on the content it holds. This can help you create better and more adaptable user interfaces.
  • You’ll avoid letting the Auto Layout system decide how to manage conflicts. When the Auto Layout system tries to solve constraint issues, it does so randomly, which could result in unexpected problems.
  • By setting lower priorities, you can increase your app’s performance. This is possible because the Auto Layout algorithm finds which constraints can be break faster. In short, not all constraints added are required.

Are you ready to get into some code? Good, because it’s time to get your hands dirty.

Practical use case

In this section, you’ll see a practical use case for applying content-hugging and compression-resistance priorities. But first, build and run the app, so you know what to expect.

img

Currently, the app displays a list of contacts. For this exercise, you’ll add the ability to see the last message received from a contact.

Open Contacts.storyboard, and select the Table View in the Contacts List Scene. Once selected, go to the Size inspector and set Row Height to 80 and make sure Automatic is unchecked.

img

Now, select ContactCell in the document outline.

img

In the Size inspector, set Row Height to 80. This will make the cell larger so that you can display the last message. Once again, make sure Automatic is unchecked.

img

Next, add a new label below the current one with the following constraints. Make sure Contrain to margins is unchecked:

  • A value of 3 from the Name Label for the Top.
  • A value of 20 from its superview for the Leading.
  • A value of 20 from its superview for the Trailing.
  • A value of 10 from its superview for the Bottom.

img

With the label still selected, go to the Attributes inspector and set Font Size to 12. Also, set Color to Dark Gray and Lines to 2.

img

The new label now has all of its constraints, but there’s still something wrong: In the top right corner of the document outline, there’s a red icon. This red icon indicates there are conflicts that Auto Layout can’t resolve on its own. Click the red icon to get more information.

img

First, there’s a message about missing constraints for both of the labels. It appears as if Auto Layout doesn’t know the height or y position for either label — that’s weird since you created the top constraints already, right?

You’ll also see there’s a Content Priority Ambiguity. What this means is that since both labels have the same level of priority, Auto Layout doesn’t know which one to stretch.

To solve these issues, select the label you just created, and in the Size inspector, navigate to the Content Hugging Priority section, which is at the bottom. In this section, you’ll see the value assigned for the horizontal and vertical priorities. By default, all elements of the UI are given a priority value of 251; change the value for the vertical priority to 250.

img

The conflicts are now gone.

By decreasing the priority for one label, you gave Auto Layout all it needs to handle the cases where there’s more room than needed for the content. In this case, it’ll stretch the message label.

Next, you need to create a connection to the label so that you can show the last message sent by the contact.

Go the Editor menu and click Assistant. Verify the code showing is for ContactTableViewCell. Now, drag a line for the Outlet to the corresponding label.

img

After the outlet is set up, ContactTableViewCell will look like this:

img

Open ContactListTableViewController.swift, and in tableView(_:cellForRowAt:), add the following line after cell.nameLabel.text = contact.name:

cell.lastMessageLabel.text = contact.lastMessage

Build and run.

img

Excellent! Thanks to you, the users can see the last message sent by their contacts on the Contact List screen.

This is a simple example of the things you can accomplish when you manipulate the content-hugging and compression-resistance priorities in your favor. It can certainly save you some headaches when creating flexible user interfaces.

Challenge

Your challenge for this chapter is to add a label to display the date of the last message on the top right corner of the contact. For this challenge, you’ll need to add a UILabelto the Contact cell. You’ll also need to add the corresponding constraints and make sure to set the proper values for the content compression-resistance priority. If all goes well, you’re updated view will look like this:

img

Notice how the label with the date and time has priority over the name of the contact.

Key points

  • The content-hugging priority represents the resistance to grow larger than the view intrinsic content size.
  • The compression-resistance priority represents the resistance to shrink beyond the view intrinsic content size.
  • Use intrinsic content size in combination with priorities to achieve adaptable user interfaces.