UIScrollView and Auto Layout

Auto Layout was introduced in iOS6 as part of Apple’s long term strategy to facilitate creating responsive apps that adapt to different screen sizes and orientations. The internal mechanics of the system and the tools to implement it are constantly improving. That, and the introduction of devices with new screen sizes over the last few years, are clear sign of what Apple wants from us: design and build apps capable of adjusting to multiple environments, offering users the best experience on each of them.

As one of the most commonly used view classes, UIScrollView and its subclasses are able to lay out their subviews using the Auto Layout system. This article explains trough an example why implementing Auto Layout in scroll views is a bit tricky and what should we do to avoid the pitfalls.

UIScrollView contentSize and Auto Layout

UIScrollView’s main purpose display content that is larger than screen area occupied by the scroll view itself. As explained in the UIScrollView basics article, to enable scrolling, the contentSize property should be set to a specific CGSize value.

By default, contentSize is {0, 0}. When we’re not using Auto Layout to place the scroll view’s subviews, we have to manually set the contentSize. With Auto Layout enabled, the contentSize is computed by the system provided that all the necessary layout constraints are properly initialized. If the system is not able to figure out the contentSized based on the Auto Layout constraints, the scroll view will not scroll. Setting the contentSize manually is simply ignored.

Case study

It’s probably easier to explain how Auto Layout works with a scroll view by showing an example.

We’ll implement a simple single view application that uses a scroll view to displays square subviews placed in multiple rows and columns evenly spaced from each other. The scroll view will only allow vertical scrolling. The size of the squares adjusts when the device orientation changes, keeping the spacing constant.

The Xcode project containing the code samples from this article is available for download here.

Setting up the scroll view

The scroll view is manually added in Interface Builder as a subview of the view controller’s main view. It is pinned to the four edges of the main view and occupies the full screen:

scroll view constraints

Make sure you disable the “Relative to the margin” option (available in Xcode 6) for the horizontal constraints:

disable relative to the margin option

Adding the subviews

Because the squares are empty UIView objects, they dont have an intrinsic content size (actually, the intrinsicContentSize property is UIViewNoIntrinsicMetric) and we have to set their width and height using Auto Layout constraints.

The square edge size is determined by dividing the scroll view’s width (same as the screen width) by the number of columns after subtracting the total spacing between the squares. There are two edge sizes, one for the portait orientation, the other for landscape.

Here is the method that adds the evenly spaced square views to the scroll view:

Conclusion

Auto Layout is not more complicated when we use it to place subviews inside an UIScrollView than in other kinds of views. We just have to bear in mind that all the subviews that form the content must have specific size metrics and be linked directly or indirectly to all four scroll views edges. Only then the system can compute the scroll view’s contentSize and enable scrolling.

 

Catalin Rosioru