Working with UIScrollView and Autolayout

Over the last few days I’ve read many, many posts on how to work with UIScrollView and Autolayout. Everything (including Apple’s documentation) is nothing but a convoluted mess. This article aims to provide the definitive source on using UIScrollViews within the Autolayout world. You can check out the source code to this demo application here.

Note that this article does assume some prior familiarity with the Autolayout system.

Embedding a view’s content within a UIScrollView is Apple’s recommended way for adjusting a view to compensate for the onscreen keyboard. Traditionally, this adjustment has been done with the use of frames. The introduction of Autolayout meant abandoning most use of frames but the need still exists to move content around on the screen with a UIScrollView and Autolayout. Here, I describe the steps involved to use these two technologies together.

To begin, there’s two ways to do it (well, really only one correct way to do it) but I’ll only be documenting one of them. The first method relies on adding subviews directly to the UIScrollView with no Container View. This is a pain because you must rely on tricks with the superview to make sure things align properly. It’s not fun.

However, the proper way to do it is easy and makes sense — once you understand it, of course!. Let’s dive right in.

1) Begin by creating a new ViewController in your project and add a UIScrollView to it.

step_1_2048x1305

2) Now, create constraints by CTRL-dragging from the UIScrollView to the View. You’ll want to create 4 constraints (hold the SHIFT key to select multiple): Leading, Trailing, Top, and Bottom constraints. Important: hold the OPTION key while doing this to align the UIScrollView to the Container (not the Container Margin).

3) Add a UIView to the UIScrollView and set up the same constraints as before: Leading, Trailing, Top, and Bottom. Notice that these constraints will already default to the Container (not the Container Margin). It’s handy to rename this newly added UIView to Content View for easier referencing later.

4) Now we’re going to add a few temporary constraints to make Interface Builder happy and for ease of understanding on our end. Add a constraint to the Content View for width and height and check the property Remove at build time:

step_4

 

This Remove at build time property will allow Interface Builder to fully compute our layout but the app will remove the constraints at runtime as they will be generated dynamically.

5) Finally, we can get to adding some content to our views. Drag a UIImageView out onto the Content View and make it 250pts wide and 250pts high, 20pts from the top, and centered along the Content View’s X axis. Additionally, make sure to add a sample image to the project so we can see something onscreen:

step_5_6_2048x1305

 

6) With this now setup add a UILabel centered on the image and spaced 500pts below it. Now, very carefully add one of the most important constraints: from the label to the Content View’s bottom. When you do this you can either set the Constant value to 0 or to Standard, whichever makes the most sense for your app. Adding these constraints should look something like this:

step_7_2048x1281

 

7) Next, add an Outlet from the Content View to a property within the ViewController class that is backing the Storyboard. I’ve named my property contentView. Like so:

step_8_2048x1281

 

8) Finally, you’ll add the following code to the viewDidLoad method of the ViewController class. This code binds the Content View’s Leading and Trailing edges to the root UIView’s edges. This allows the UIScrollView to implicitly calculate it’s contentSize and render the view appropriately. Run the app and you should have a label below your image and scrolling working as expected!

Following these steps should result in a functioning UIScrollView with Autolayout. I won’t cover the steps involved to show and hide the keyboard but that’s all covered in the aforementioned article by Apple.