AlexFZ AlexFZ - 3 months ago 18
iOS Question

UIImageView/UIScrollView forcing a fixed aspect ratio to fit the screen

I am making a simple app for the iPad that consists of a giant image that you can zoom-in/out on and navigate.

This image is placed inside a

UIImageView
, which is then placed inside a
UIScrollView
.

The navigation and zooming work 100% fine; however, the image is loaded at a fixed aspect-ratio to fit the screen, and will never change (even when zooming-in).

I have a feeling that Interface Builder is setting some property that I'm not aware of, but I've tried everything that I can think of to fix this.

The Problem:

When the app initially loads, the contents inside the
UIScrollView
is automatically re-sized to exactly fit the iPad screen by having its aspect ratio changed./fixed; the actual image is giant (way bigger than the iPad resolution). This scaled aspect ratio remains even when zooming in on the image, and causes the image to look stretched.

No matter what I try, I cannot stop the iPad from automatically rescaling my image. I simply want the app to start with my image displayed normally (100% zoom) on the iPad, with the portion that currently fits on the iPad screen being the top-left corner of the image.

What I've tried to fix it:

I tried changing the
UIImageView's
content-mode in Interface Builder to "Top-Left". This appeared to work perfectly, but then I realized that the
UIScrollView
would not let you scroll around the image past the initially displayed portion (the top-left). You could zoom-in on the top-left portion and scroll, but never past what was initially shown on the screen.

Code:

Here's the code that I'm using to setup the views.
imageScrollView
is the
UIScrollView
, and
imageView
is the
UIImageView
. They are both
IBOutlets
.

// Set the needed attributes of the imageView
[imageView setImage:[UIImage imageNamed: @"TestImage.png"]];
imageView.userInteractionEnabled = YES;

// Set a bunch of the imageScrollView attributes.

// calculate minimum scale to perfectly fit image width, and begin at that scale
float minimumScale = [imageScrollView frame].size.width / [imageView frame].size.width;
[imageScrollView setMinimumZoomScale:minimumScale];
[imageScrollView setZoomScale:1];
[imageScrollView setMaximumZoomScale:10];
[imageScrollView setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
[imageScrollView setScrollEnabled:YES];
[imageScrollView setUserInteractionEnabled:YES];
imageScrollView.clipsToBounds = YES;
imageScrollView.bounces = FALSE;
imageScrollView.bouncesZoom = FALSE;


I also have two
UIGestureRecongizers
to handle tap-zooming, but I do not believe that they are the issue. When I comment them out, nothing changes.

Any help would be extremely appreciated.

Answer

I fixed it!

For anyone else having the same problem, here's how I fixed the code:

The Cause of the bug was that Interface Builder was forcing the views to use the ScaleToFill contentMode. Setting the ScrollView's contentMode to UIViewContentModeScaleAspectFit didn't work on its own, since the imageView was still being distorted.

The Fix:

The following code had to be added at the end of the setup for the UIScrollView and UIImageView (inside of the viewDidLoad() method):

    [imageScrollView setContentMode:UIViewContentModeScaleAspectFit];
    [imageView sizeToFit];
    [imageScrollView setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];

Explanation:

First, the UIScrollView's contentMode is set to AspectFit, like @Mike suggested. Then, sizeToFit() is called on the imageView to override Interface Builder's annoying presets, and to make the image the correct size.

The last line is important. You must set the contentSize for the ScrollView AFTER you re-size the imageView. Otherwise, the ScrollView will think that the image is still the size of the iPad display, and therefore won't think that there's anything to scroll. Setting the size of the ScrollView after resizing the ImageView and changing the ScrollView's contentMode makes the ScrollView the actual size of the image.

Hope that helped!

Thanks for the help Mike, it got me on the right track :)

  • Alex
Comments