Setting UIScrollView zoom scale to fit the screen

23,552

Solution 1

The solutions above work, but I was struggling to understand why. I would like to share these two articles that I found extremely helpful in setting the mininumZoomScale correctly and getting this to work with iOS8/XCode 6.

First, getting the scroll view to work on iOS8 demands that you set your constraints correctly from the start. Other posters have recommended, and I agree, that your scroll view should only ever have a single content view. Fine to embed all of your other views within the one content view, but you don't want to set your scroll view constraints to a bunch of little views.

Connect your Top, Leading, Trailing, and Bottom constraints to the scroll view from the content view (in my case it is an UIImageView) with constant 0. This sets the edges of your content view to the scroll view.

Next, set the size of the content view using the Equal Width and Equal Height constraints to the scroll view. You can't use Fixed Width and Fixed Height in the content view because zooming won't work, nor can you manage the size yourself. Without these constraints, iOS8 sets the size to (0,0) before you have a chance resulting in some odd artifacts. With these constraints, call your updateZoom method in the orientation method and you are good. In iOS7 call it in didRotateFromInterfaceOrientation. In iOS8 call it from viewWillTransitionToSize. You'll need to update the code to pass in the new size.

Many thanks to Natasha The Robot for the constraint solution: http://natashatherobot.com/ios-autolayout-scrollview/

When you call your updateZoom method to tweak your minimum, you should also check whether your current zoomScale is < your minimumZoomScale and reset it if it is. You should not reset the zoomScale otherwise as this becomes another quizzical look from your user when orientation changes.

As for the rest of it and why the math works, Joe Conway at objc.io laid it all out in this fantastic article on bounds vs. frame with UIScrollViews: http://www.objc.io/issue-3/scroll-view.html

Thanks to both and the poster's above.

-(void)updateZoom {
    self.scrollView.minimumZoomScale = MIN(self.scrollView.bounds.size.width / self.imageView.image.size.width, self.scrollView.bounds.size.height / self.imageView.image.size.height);

    if (self.scrollView.zoomScale < self.scrollView.minimumZoomScale)
        self.scrollView.zoomScale = self.scrollView.minimumZoomScale;
}

Solution 2

The solution was fairly easy... Check out this code (modified version of method from OP):

- (void)updateZoom {
    float zoomScale = MIN(self.view.bounds.size.width / self.imageView.image.size.width, self.view.bounds.size.height / self.imageView.image.size.height);

    if (zoomScale > 1) {
        self.scrollView.minimumZoomScale = 1;
    }

    self.scrollView.minimumZoomScale = zoomScale;
    self.scrollView.zoomScale = zoomScale;
}

I think there is nothing to explain as the code is straight forward.

Solution 3

SWIFT 3

Thanks to @chewy this worked for me (I needed to add "bounds" to the image):

func setZoomScale() {

    var minZoom = min(self.view.bounds.size.width / imageView!.bounds.size.width, self.view.bounds.size.height / imageView!.bounds.size.height);

    if (minZoom > 1.0) {
        minZoom = 1.0;
    }

    scrollView.minimumZoomScale = minZoom;
    scrollView.zoomScale = minZoom;

}

Then call setZoomScale() in "override func viewWillLayoutSubviews()"

Solution 4

To set the zoom which fits the image size in scrollView set the the minimumZoom for scrollView using this : self.scrollView.minimumZoomScale = self.scrollView.frame.size.width/ self.imageView.frame.size.width;

Above code will fit your image in the scrollView Width.

Solution 5

And here is the Swift 3 version

var minZoom = min(self.view.bounds.size.width / theImage!.size.width, self.view.bounds.size.height / theImage!.size.height)
if minZoom > 1.0 {
    minZoom = 1.0
}

self.scrollImg.minimumZoomScale = minZoom
self.scrollImg.zoomScale = minZoom
Share:
23,552
cojoj
Author by

cojoj

Updated on February 28, 2020

Comments

  • cojoj
    cojoj about 4 years

    My point is to copy the behaviour of many apps which uses photos where when UIScrollView with UIImageView inside is being presented it fits image to the size of screen even if this image is smaller.

    I'm certain that this shouldn't be done with UIImageView frame but manipulated by UIScrollView but how...?


    In my code I have a method called updateZoom which calculates the minimumZoomScale value and also assigns this value to the zoomScale property. I guess that this is the right place to do math and calculate zoomScale manually.

    This is the method:

    - (void)updateZoom {
        float minZoom = MIN(self.view.bounds.size.width / self.imageView.image.size.width, self.view.bounds.size.height / self.imageView.image.size.height);
    
        if (minZoom > 1) {
            minZoom = 1;
        }
    
        self.scrollView.minimumZoomScale = minZoom;
        self.scrollView.zoomScale = minZoom;
    }
    

    I hope that someone would give me a hit on how to set the zoomScale to fit the UIScrollView bounds.