Scroll Views in XCode 11
Learn how to efficiently display scrollable content in iOS apps
As a new programmer (I guess not even there yet), I’m constantly finding answers for my “quests”, that do not completely conform with the actual version of iOS or XCode. One of these examples is the way that Scroll Views are now implemented by default in XCode 11.
If you try and follow along with the online tutorials and StackOverflow answers about ScrollView implementations, I guess 90% of those are still related to the old way of doing it. It is not big of a difference conceptually, but it’s enough to get your head banging against the wall if you start to follow along with those tutorials and guides in XCode 11. I’ve been there and done that. So I thought, “I must figure this out, no matter what”. So what you are about to see, is 90% equal to what you can find all over the internet, but with the addition of the small “big” change introduced in XCode 11.
What is a Scroll View?
A Scroll View for those who are even more beginners than I am, as the name implies, is what allows you to scroll through content in your iOS device. You can find them everywhere, whether it is a vertical scroll, whenever your content is presented as a list, (Email App, the Files App, Facebook, you name it); a horizontal scroll (less common but you can find it in some content Apps where the Categories are presented horizontally, check IMDB for instance); and both horizontal and vertical (the common example to present here is the Photos App, where you can double click on a photo to zoom and then you scroll the photo in both directions back and forth).
For that to work in Auto Layout, the Scroll View object needs to have a size (width and height) and a placement in its Superview (x and y). For the purpose of this article let’s call this, a Frame Layout. It also needs to know the width and height of the content to present. Let’s call it, a Content Layout. Remember those two terms and what they mean in bold, Frame Layout and Content Layout. Read this paragraph again if it is not clear in your mind yet.
So what is the difference?
As I mentioned in the beginning of the article there is a small difference introduced in XCode 11. The theory and concepts are the same, but the default implementation of Auto Layout in Interface Builder to prepare a Scroll View to act as pretended is a bit different. And it is for better if you ask me because it makes the concept explained before, much clearer and less prone to errors when building your Interface. But… If you are not aware of that change, you try and use all those tutorials out there, it simply won’t work…
When you drag a Scroll View to your ViewController you need to deal with the constraints in order to conform to the AutoLayout rules for the Scroll View (remember the Content Layout and Frame Layout?). But before, that was not explicit in the steps you needed to perform to achieve it. From my limited experience, you had to deal with a lot of constraints errors, before you got rid of all those red lines in IB. I’m not gonna follow that path, because as said before if you want to do it that way you can find a lot of articles out there.
Now, when you drag a Scroll View to Interface Builder, by default you find a couple of new options already prepared for you.
Remember the Content Layout and Frame Layout? Now, the guides are there for you and can be “easily” used to help you out setting your ScrollView to act as needed.
By the way, if want to use the “old way”, just uncheck the Content Layout Guides in the Size Inspector.
After you set the Constraints for those two Guides you are all set to build your UI, using Scroll Views, weather you want them to be dynamically sized or with a fixed size. Let’s see how can we do that:
Setting the Constraints using Content Layout Guide
So do you still remember the meaning of Content Layout? It is the size and position of the content you want to present in the Scroll View. It gets easier as you do it more often but is important to understand it from the beginning. In the picture above a Scroll View is already placed in its Superview. If you haven’t done already do it now in your project to follow along.
After placing the Scroll View in the View Controller, just drag the edges to match the edges of the Superview (if you want you can also set it to match the Safe Area. It’s up to you and your preference, but the setup is the same). Then just Add New Constraints, pinning the Scroll to whichever edges you like. In the example, we are pinning it to the edges of the Superview on all sides.
Although it seems you are taking care of the Size and Placement of the Scroll View — Frame Layout — you are just giving some space to drag some content to the Scroll View. As you can see, we still have some red lines and AutoLayout issues.
We’ll deal with that soon, but the problem is that Interface Builder still doesn't know the size of the content to be presented and consequently the size of the Scroll View.
A Scroll View is “invisible” as a UI object. You need to place some content inside it to be presented. And the easiest way to make it dynamically sized is to add an object that automatically adjusts its size based on the content inside. That’s why we should use a Stack View. Alternatively, if you want to use a fixed size view, you can just drag a “regular” View Object and set its width and height as you please. In the example, we use a Vertical Stack View.
Our immediate response (at least mine), would be to start and drag the edges to match the Scroll View, but we’ll do that in a different way.
On the Document Outline CTRL+Drag the Stack View entry to the Content Layout Guide. Remember what are we trying to do? We want to set the size of the Content to be presented! After you Drag a popup will appear. Press Shift and select the Leading/Top/Trailing/Bottom constraints. We are saying to Interface Builder that we want our content to match the placement of the Content Layout Guide. In other words, we are setting the Content Layout position.
As we didn’t drag the edges of the Stack View, Interface Builder assumes what was there instead. To force the Scroll View to go to the edges of our screen we should edit the Constraints. Select the Stack View in the Document Outline, and go to the Size Inspector. You will see the Constraints you just built. Press Edit in each one of them and set it to 0.
We’re not there yet. You still have red lines and a “small” Stack View in the middle of your UI. But bare with me. It will all make sense soon. Actually is making sense now already. The Interface Builder still doesn’t know the size of the Content you want to present. That’s why it is giving you the red lines.
Setting Constraints using Frame Layout Guide
In this example, we just want to scroll vertically. If you think about the act of scrolling only vertically, the leading and trailing edges don’t move. We only have “movement” from bottom to top and vice-versa. Meaning that we don’t have width variations. So we need to tell Interface Builder that our content should be equal or lesser than the Scroll View width. Makes sense?
For that, CTRL+Drag the Stack View to the Frame Layout Guide entry as we did before. In this case, just select Equal Widths.
Most probably, XCode created a less than 1 proportion based on the size of the Stack View you had.
As we did before, go to the Size Inspector and set the Multiplier parameter to 1. I mean, do this, only if you want the content to match the width edges of the Scroll View. If you need it smaller than that, adjust it accordingly or let be as is.
Wait! But why are we still getting red lines???
Any guesses why? You’re right because the Stack View is waiting for content and therefore to have a size!!!
As soon as you place any View inside the Stack View, its size will automatically adapt and the red lines are gone!!! You don’t believe me? So go on, and drag a Label inside the Stack View. As soon as you do that, the red lines are gone!!!
Now to see the horizontal scroll in action, you just need to add enough text to the Label, to make it bigger than the screen. You can do that by selecting the Label and updating the text parameter with a big enough text. Also don’t forget to set the Number Of Lines parameter to 0, in order for the label adjust the number of lines automatically.
As soon as you do it, you can then select the Stack View in the Document Outline, and scroll through the content to see it in action! You can also see the size of the content by following the blue lines.
I seriously doubt that you want your App to conform to the previous screenshot appearence 😀. I did that on purpose because now you can see what it means to use the Safe Area in Auto Layout. At the beginning of this article we pinned the Scroll View to the edges of the Superview. Go back to see that if you have any questions about it. That is why the text stretches all the way up, left and right.
But if you select each Scroll View Constraint in the Document Outline, you can now change the reference to the Safe Area instead of Superview. Make sure you have the Constant parameter set to 0 in the top and bottom, to 20 on the leading and to -20 on the trailing.
After those changes you should end up with something similar to this:
If you then run your App in the Simulator, you should see the text scrolling smoothly, top to bottom!
I really hope that you find this useful, and from now on, Scroll Views in Xcode 11 won’t scare you as much. I mean if you are a beginner like me, of course…🤓
You can find the project here: