UIScrollView zooming with Auto Layout

phu picture phu · Dec 25, 2012 · Viewed 10.9k times · Source

I'm trying to implement a UIScrollView the New Way, using Auto Layout. I've set up constraints from the inner view to the scroll view so that it can compute its own contentSize automatically, and that works like a charm— except that all hell breaks loose when I try to zoom in or out. I can't even properly describe what happens, other than to say that the inner view gets "messed up".

You can see an example of this behavior here (not my project; you have to set the scroll view's maximumZoomScale and implement -viewForZoomingInScrollView: before zooming will work).

Has anyone else run into this behavior? Is there currently any way to get zooming in a UIScrollView to work with Auto Layout without essentially re-implementing the zooming behavior yourself?

Answer

Chris Conover picture Chris Conover · Apr 23, 2013

The best answer that I have seen is Mark's (https://stackoverflow.com/users/1051919/mark-kryzhanouski), posted here: UIScrollView Zoom Does Not Work With Autolayout.

The crux of it is that you have to anchor the image view that is nested in the scroll view, to the parent of the scroll view. Despite the guidance in the iOS 6 release notes, it is not intuitive to me what view is "floating" over what. In this case, the scrolling view is just a single image view.

I did do a lot of experimentation with this, hoping to find an all-IB approach and found none. You can still generate the view hierarchy in IB, but you still have to programatically add constraints. You can delete some or all of the default constraints (mainly just to appease the constraint-conflict warnings), but you always need Mark's code to tie the image view to the parent of the scroll view, the grand-parent of the image view.

It seems like it should be simpler than this - it "should just work" but:

NSDictionary *viewsDictionary = @{ @"scrollView": self.scrollView, @"imageView": self.imageView };
[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:|[imageView(width)]"
    options:0
    metrics:@{@"width": @(self.imageView.image.size.width)}
    views:viewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|[imageView(height)]"
    options:0
    metrics:@{@"height": @(self.imageView.image.size.height)}
    views:viewsDictionary]];