Ios – Resetting UIScrollView’s zoomScale property on autorotation

autorotateiosiphonescale

I have a custom UIViewController onto which I've added a UIImageView (on the StoryBoard) and then embedded the UIImageView in a UIScrollView. My program loads an image into the imageView and scales it to properly fit. By proper fit, I mean this:

  • if the aspect ratio of the image exactly matches that of the view, the image will be scaled to exactly fit the view, with no scroll bars
  • otherwise, the image will be scaled to exactly fit in one dimension, with a scrollbar in the other dimension.

I currently do this in viewWillAppear. Below is my code for that method and an auxiliary method that calculates the correct zoomScale:

-(float) findZoomScale {    
    float widthRatio = self.view.bounds.size.width / self.imageView.image.size.width;
    float heightRatio = self.view.bounds.size.height / self.imageView.image.size.height;
    float ratio;
    if (widthRatio > heightRatio) ratio = widthRatio;
    else ratio = heightRatio;
        return ratio;
}

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:YES];
    self.imageView.image = self.image;
    self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
    self.scrollView.contentSize = self.imageView.image.size;
    self.scrollView.zoomScale = [self findZoomScale];
        [self.scrollView flashScrollIndicators];
}

- (void)viewDidLoad {    
    [super viewDidLoad];
    self.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:self.photoURL]];
    self.imageView.image = self.image;
    self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, 
        self.imageView.image.size.height);
    self.scrollView.delegate = self;
    self.scrollView.zoomScale = 1.0;
    self.navigationItem.title = self.photoTitle;
    self.scrollView.autoresizesSubviews = YES;
    self.scrollView.autoresizingMask = (UIViewAutoresizingFlexibleBottomMargin | 
        UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | 
        UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth | 
        UIViewAutoresizingFlexibleHeight);
}

This code works as I intended for the initial load of an image, whether the iPhone is in landscape or portrait orientation. But when I then rotate the iPhone with the image already loaded, it does not properly rescale. I have tried to do the rescaling in didRotateFromInterfaceOrientation, playing with the scrollView's zoomScale property, but I can't get it to work. Is this the correct place to do the rescaling? And if so, how do I do it? Thanks.

Duane

Best Answer

I just had this exact problem (I assume you're on the CS193p assignment 4 as well), and solved it by setting the zoomScale back to 1 before adjusting the UIScrollView's contentSize upon rotation.

For example:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    //reset zoomScale back to 1 so that contentSize can be modified correctly
    self.scrollView.zoomScale = 1;

    // reset scrolling area equal to size of image
    self.scrollView.contentSize = self.imageView.image.size;

    //reset the image frame to the size of the image
    self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);

    //set the zoomScale to what we actually want
    self.scrollView.zoomScale = [self findZoomScale];
}
Related Topic