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?
UIScrollView is the superclass of several UIKit classes, including UITableView and UITextView . A scroll view is a view with an origin that's adjustable over the content view. It clips the content to its frame, which generally (but not necessarily) coincides with that of the app's main window.
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]];
Without adding an imageView in the storyboard, I've found the following works perfectly:
-(UIImageView *)imageView { if (!_imageView) _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; return _imageView; } - (void)viewDidLoad { [super viewDidLoad]; [self.scrollView addSubview:self.imageView]; // Set the min and max: self.scrollView.minimumZoomScale = 0.2; self.scrollView.maximumZoomScale = 5.0; self.scrollView.delegate = self; // Set the content: self.scrollView.zoomScale = 1.0; // reset zoomScale for new image self.scrollView.contentSize = CGSizeMake(image.size.width/2, image.size.height/2); self.imageView.frame = CGRectMake(0, 0, image.size.width/2, image.size.height/2); self.imageView.image = image; } -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return self.imageView; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With