Search code examples
iosswiftscrollview

How to define proper constraints for scrollview to work effectively


My storyboard layout is simple as shown in the attached image. I am assuming that the body text could span from a single line to multiple lines. Considering the case of multiple lines, I expect the content to scroll so that the button can be clickable. However, with the constraints I have set, the scroll view does not scroll. What constraints should I change in order to get the desired effect? Thank you.

constraints defined


Solution

  • The key to using UIScrollView: You must have a "chain" of constraints to allow auto-layout to determine the .contentSize of the scroll view.

    Step-by-step (I like to set background colors during layout, to make it easy to see the bounds / frames of the elements)...

    Add a UIScrollView (Cantaloupe color) to your view controller, and constrain it by 20-pts all the way around (just so we can see where it is):

    enter image description here

    Add a UIView as your ContentView (Strawberry color) as a subview of the scroll view. Give it equal Height and Width constraints to the scroll view, and top / leading / trailing / bottom constraints all set to 0:

    enter image description here

    Add your Title UILabel (Yellow background). Constrain it Top: 30 / Leading: 50 / Trailing: 50. Add your Body UILabel (Yellow background). Constrain its Top to the Title label's Bottom (I used 200), and Leading: 10 / Trailing: 10. Add your UIButton (Light Gray background). Constrain its Top to the Body label's Bottom (I used 50), and Leading: 50 / Trailing: 50:

    enter image description here

    So far, nothing special, and you won't get any scrolling...

    Next, add another Bottom constraint of 0 to the ContentView, and change the first Bottom constraint to be >= 0 and set the Priority of the new Bottom constraint to 250:

    enter image description here

    This will (after a couple more steps) allow ContentView to expand / collapse based on its content, as well as control the .contentSize of the scroll view.

    The next step is to tell the Button to determine the Height of the ContentView - so add a Bottom constraint of 30 to the button (which will be equal to the Top: 30 we gave to the title label):

    enter image description here

    Of course, that's not quite what we want. It stretches the height of the button because we set a height constraint on the ContentView. So... delete the height constraint from the ContentView:

    enter image description here

    The result is that the ContentView height will shrink to fit 30-pts below the bottom of the button.

    If you add some more text to the Body label (assuming it is set to Number of Lines; 0), you will see the Body label expand and "push down" the button, which in turn "pushes down" the bottom of ContentView:

    enter image description here

    If you add enough text to Body to push the button below the bottom of the scroll view - either in IB or via code - it will now scroll vertically.

    Hope that's clear... please ask if you have any questions.