9

I have a UILabel inside a UIScrollView that I am trying to word wrap. I want to use AutoLayout for the layout configuration. The UILabel word wraps perfectly when it is not inside a UIScrollView. I just have to set the number of lines to 0 and set the line break mode to word wrap.

However, when I put the UILabel inside a UIScrollView, the word wrapping ceases to work. I have already checked "Dynamic UILabel height inside UIScrollView with AutoLayout" and "Correctly Size UILabel inside UIScrollView using Interface Builder and Autolayout?", but neither of those questions have answers that help me.

I have set up a test project illustrating exactly what I am talking about if someone wants to have a look at it.

Community
  • 1
  • 1
Adam Johns
  • 35,397
  • 25
  • 123
  • 176
  • Actually the answers to the questions you cite are exactly what you need. The problem is that you are not listening to what they tell you. – matt Oct 28 '14 at 13:49

3 Answers3

18

The reason is that constraints inside a scroll view, pinned to the scroll view, do not mean what you think they mean. They have to do with determining the contentSize of the scroll view from the inside out; they do not of themselves determine the size of the things inside the scrollview from the outside in. See my answer here: https://stackoverflow.com/a/13548039/341994

The simplest solution in your case is to use an intermediate content view, so that you have this hierarchy:

scroll view
    content view
        label

Now give the content view absolute width and height constraints and pin it on all four sides to the scroll view. Now the label will work as you expect. The content view has sufficient constraints both to set its own size absolutely and to constrain the scroll view's contentSize from the inside. The constraints on the label, meanwhile, are not to the scroll view but to the content view, and since the content view has a fixed size and is a normal view (not a scroll view), the constraints on the label do what you expect.

Community
  • 1
  • 1
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 1
    If you look carefully at the project you posted, you will see that Xcode is actually telling you this. There is a warning on the layout structure of the scroll view. That warning is effectively telling you the same thing I'm telling you here. Do not ignore auto layout warnings in Xcode! They _mean_ something. – matt Oct 28 '14 at 13:48
  • Thanks so much for your answer, it is helping me to understand what is happening. However, what is this `content view` you are speaking of? Container View? – Adam Johns Oct 28 '14 at 13:52
  • It is a plain vanilla UIView whose purpose is to do what I just described - to act as an intermediate view so that the `contentSize` will be set and internal constraints will work. – matt Oct 28 '14 at 14:28
  • I've fixed your example on github in a fork and created a pull request. It's a lot easier to show you than to describe it in words! – matt Oct 28 '14 at 14:46
  • 1
    Thanks so much for taking the time to help me out. I now understand that the content view is what controls the scrollviews content size for scrolling. I have successfully recreated what you have taught me. Thanks again. – Adam Johns Oct 28 '14 at 16:19
  • You're very welcome. I'm still wondering how the heck I would have explained this if you hadn't given me a github repository to work with! :) – matt Oct 28 '14 at 17:43
  • Thanks for the tip, in my case I wanted to wrap a label with constant leading and trailing spaces in different different screens. In that case I didn't set a with and a height for the content view. Instead of that, I just make make it **center horizontal** to the scroll view. – enadun Jul 21 '15 at 09:00
8

I had the same issue, but was able to get the UILabel to wrap correctly by setting up the following constraints on the label

  • Leading Space to Superview
  • Trailing Space to Superview
  • Equal Width to Superview **(This is the one that constrains the width on the label so it will wrap properly)

You also must have constraints leading from the top to the bottom of the scroll view. For instance, if you only have the label you must set Top Space and Bottom Space to Superview. If you don't, it will have an ambiguous scrollable content height.

To prevent horizontal scrolling of the scroll view, check "Direction Lock Enabled" and call setContentOffset properly inside the scrollViewDidScroll method (see the first answer for this question for the details).

Community
  • 1
  • 1
Donovan
  • 301
  • 2
  • 8
2

Try using UILabel's preferredMaxLayoutWidth and set it to parent's view width.

SoftDesigner
  • 5,640
  • 3
  • 58
  • 47