Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollView Scrollable Content Size Ambiguity

Fellow devs, I am having trouble with AutoLayout in Interface Builder (Xcode 5 / iOS 7). It's very basic and important so I think everyone should know how this properly works. If this is a bug in Xcode, it is a critical one!

So, whenever I have a view hierarchy such as this I run into trouble:

>UIViewController >> UIView >>>UIScrollView >>>>UILabel (or any other comparable UIKit Element) 

The UIScrollView has solid constraints, e.g., 50 px from every side (no problem). Then I add a Top Space constraint to the UILabel (no problem) (and I can even pin height / width of the label, changes nothing, but should be unneccessary due to the Label's intrinsic size)

The trouble starts when I add a trailing constraint to the UILabel:

E.g., Trailing Space to: Superview Equals: 25

Now two warnings occur - and I don't understand why:

A) Scrollable Content Size Ambiguity (Scroll View has ambiguous scrollable content height/width)

B) Misplaced Views (Label Expected: x= -67 Actual: x= 207

I did this minimal example in a freshly new project which you can download and I attached a screenshot. As you can see, Interface Builder expects the Label to sit outside of the UIScrollView's boundary (the orange dashed rectangle). Updating the Label's frame with the Resolve Issues Tool moves it right there.

Please note: If you replace the UIScrollView with a UIView, the behaviour is as expected (the Label's frame is correct and according to the constraint). So there seems to either be an issue with UIScrollView or I am missing out on something important.

When I run the App without updating the Label's frame as suggested by IB it is positioned just fine, exactly where it's supposed to be and the UIScrollView is scrollable. If I DO update the frame the Label is out of sight and the UIScrollView does not scroll.

Help me Obi-Wan Kenobi! Why the ambiguous layout? Why the misplaced view?

You can download the sample project here and try if you can figure out what's going on: https://github.com/Wirsing84/AutoLayoutProblem

Illustration of the problem in Interface Builder

like image 533
Wirsing Avatar asked Sep 26 '13 18:09

Wirsing


People also ask

What is scroll view content size?

The content size of a scroll view doesn't change anything about the bounds of a scroll view and therefore does not impact how a scroll view composites its subviews. Instead, the content size defines the scrollable area. By default, a scroll view's content size is a big, fat {w:0, h:0} .

Can stack view be scrollable?

Scrolling only happens when the content view inside the scrollview is larger than the scrollview! To elaborate on point 6. If the stack view had no elements but all the constraints are in place, you get "Scroll View Need constraints for Y position or height".

What is content layout guide in Scrollview?

The Content Layout guide relates to the size of the scrollable content area inside the scroll view. The challenging part is to define enough constraints to let Auto Layout calculate the scrollable content area (Content Layout) width and height, which we will go into in the next section.


1 Answers

So I just sorted out in this way:

  1. Inside the UIScrollView add a UIView (we can call that contentView);

  2. In this contentView, set top, bottom, left and right margins to 0 (of course from the scrollView which is the superView); Set also align center horizontally and vertically;

Update:

Nowadays, Apple realized the problem we solved many years ago (lol_face) and provides Content Layout Guide and Frame Layout Guide as part of the UIScrollView. Therefore you need to go through the following steps:

  1. Same as above;

  2. For this contentView, set top, bottom, left, and right margins to 0 pinning them to the Content Layout Guide of the scroll view;

  3. Now set the contentView's height equal to the Frame Layout Guide's height. Do the same for the width;

  4. Finally, set the priority of the equal height constraints to 250 (if you need the view to scroll vertically, the width to scroll horizzontally).

Finished.

Now you can add all your views in that contentView, and the contentSize of the scrollView will be automatically resized according with the contentView.

Don't forget to set the constraint from the bottom of the last object in your contentView to the contentView's margin.

like image 113
Matteo Gobbi Avatar answered Oct 06 '22 15:10

Matteo Gobbi