1
votes

I have been trying to implement autolayout on a UIScrollView but have been struggling. Here is a description of my main view, from top to bottom: Navigation bar -> Scroll View -> UITextField, all of which stretch horizontally across the screen. Here are the constraints for these three views:

//Vertical constraints; this appears to be working fine
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-navHeight-[_inputScrollView][_inputField(inputFieldHeight)]|" options:0 metrics:metricsDict views:viewsDict]];


//Horizontal Constraints; these also appear to be working fine
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_inputScrollView]|" options:0 metrics:metricsDict views:viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_inputField]|" options:0 metrics:metricsDict views:viewsDict]];

Next, as countless UIScrollView/autolayout tutorials suggest, I added a subview to the UIScrollView to act as a content view for many other subviews, which will be added dynamically at runtime. So when the application launches there will be nothing in the content view. Here are what the constraints for my content view look like:

//Left constraint, pinning the content view to the left edge of the screen
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:_contentView
                                                                  attribute:NSLayoutAttributeLeading
                                                                  relatedBy:0
                                                                     toItem:self.view
                                                                  attribute:NSLayoutAttributeLeading
                                                                 multiplier:1.0
                                                                   constant:0];
[self.view addConstraint:leftConstraint];

//Right constraint, pinning the content view to the left edge of the screen
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:_contentView
                                                                   attribute:NSLayoutAttributeTrailing
                                                                   relatedBy:0
                                                                      toItem:self.view
                                                                   attribute:NSLayoutAttributeTrailing
                                                                  multiplier:1.0
                                                                    constant:0];
[self.view addConstraint:rightConstraint];

//Top constraint, setting the top of the content view
//to be offset from the top of the main view
//by the height of the navigation bar
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:_contentView
                                                                   attribute:NSLayoutAttributeTop
                                                                   relatedBy:0
                                                                      toItem:self.view
                                                                   attribute:NSLayoutAttributeTop
                                                                  multiplier:1.0
                                                                    constant:navHeight.floatValue];
[self.view addConstraint:topConstraint];

//Bottom constraint, setting the bottom of the content view 
//to be offset from the bottom of the main view by the 
//height of the text field.
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:_contentView
                                                                 attribute:NSLayoutAttributeBottom
                                                                 relatedBy:0
                                                                    toItem:self.view
                                                                 attribute:NSLayoutAttributeBottom
                                                                multiplier:1.0
                                                                     constant:-inputFieldHeight.floatValue];
[self.view addConstraint:bottomConstraint];

After these views are laid out, the height of my content view is equal to the height of my scroll view. I have the alwaysBounceVertical property set to YES, so I expect to see some scrolling. When I scroll on the screen, the content offset of my scroll view does change! I implemented scrollViewDidScroll and logged the contentOffset to the screen. However, the content view does not move at all. I set the background color of the scroll view to be red and the background color of the content view to be black. When the contentOffset is changing, you still never see any of the red scrollview. The content view is a subview of the scrollview, so why in the world is its frame not changing?! Any help would be so so so so so appreciated. Thanks!

1

1 Answers

1
votes

I had to set up my constraints in the following way:

1) Tie to content view to the scroll view by adding top, bottom, left, and right constraints (e.g. top of content view = top of scroll view). 2) Define explicit height and width constraints for the content view. In my case, and in most cases, the constants for these constraints should be based off of the height/width of the content view's subviews.

Once I implemented this design scrolling worked appropriately.