I have an ImageZoom class that subclasses UIView and is a delgate for the UIScrollView. It's pretty straight forward. The class contains a UIScrollView which contains a UIImageView. When an instance of the class is added to a view controller the image is zoomed so that it is flush with the view. There is a method that zooms in when you double tap and zooms out when repeated. Everything works great except for when I change orientation to landscape. I can't seem to figure out how to get the zoom right so that the image is now flush with the new orientation. Here is a link to file as well:
http://www.2shared.com/file/bowDjzLr/imagescroll.html
ViewController.h
#import <UIKit/UIKit.h>
#import "ImageZoom.h"
@interface ViewController : UIViewController
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong) ImageZoom *imageZoom;
@property (nonatomic, strong) UIImage *image;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.image = [UIImage imageNamed:@"1.png"];
}
-(void)viewDidAppear:(BOOL)animated
{
ImageZoom *imageZoom = [[ImageZoom alloc]initWithImage:self.image andFrame:self.view.bounds];
self.imageZoom = imageZoom;
[self.view addSubview:imageZoom];
}
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self.imageZoom willAnimateToFrame:self.view.bounds];
}
@end
ImageZoom.h
#import <UIKit/UIKit.h>
@interface ImageZoom : UIView <UIScrollViewDelegate>
- (id)initWithImage:(UIImage *)image andFrame:(CGRect)frame;
-(void)willAnimateToFrame:(CGRect)frame;
@end
ImageZoom.m
#import "ImageZoom.h"
@interface ImageZoom ()
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIScrollView *scrollView;
@property BOOL zoomed;
@end
@implementation ImageZoom
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self loadContent];
}
return self;
}
-(void)loadContent
{
self.scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
self.scrollView.delegate = self;
self.scrollView.contentSize = self.image.size;
[self.scrollView addSubview:self.imageView];
[self addSubview:self.scrollView];
CGRect scrollViewFrame = self.scrollView.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / self.scrollView.contentSize.width;
CGFloat scaleHeight = scrollViewFrame.size.height / self.scrollView.contentSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
self.scrollView.minimumZoomScale = minScale;
self.scrollView.maximumZoomScale = 1;
self.scrollView.zoomScale = minScale;
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrollViewDoubleTapped:)];
doubleTapRecognizer.numberOfTapsRequired = 2;
doubleTapRecognizer.numberOfTouchesRequired = 1;
[self.scrollView addGestureRecognizer:doubleTapRecognizer];
}
-(void)willAnimateToFrame:(CGRect)frame
{
self.scrollView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
CGRect scrollViewFrame = self.scrollView.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / self.scrollView.contentSize.width;
CGFloat scaleHeight = scrollViewFrame.size.height / self.scrollView.contentSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
self.scrollView.minimumZoomScale = minScale;
self.scrollView.maximumZoomScale = 1;
self.scrollView.zoomScale = minScale;
CGPoint centerPoint = CGPointMake(CGRectGetMidX(self.scrollView.frame), CGRectGetMidY(self.scrollView.frame));
[self view:self.imageView setCenter:centerPoint];
}
- (void)view:(UIView*)view setCenter:(CGPoint)centerPoint
{
CGRect viewFrame = view.frame;
CGPoint scrollViewContentOffset = self.scrollView.contentOffset;
CGFloat x = centerPoint.x - viewFrame.size.width / 2.0;
CGFloat y = centerPoint.y - viewFrame.size.height / 2.0;
if(x < 0)
{
scrollViewContentOffset.x = -x;
viewFrame.origin.x = 0.0;
}
else
{
viewFrame.origin.x = x;
}
if(y < 0)
{
scrollViewContentOffset.y = -y;
viewFrame.origin.y = 0.0;
}
else
{
viewFrame.origin.y = y;
}
view.frame = viewFrame;
self.scrollView.contentOffset = scrollViewContentOffset;
self.zoomed = NO;
}
- (id)initWithImageView:(UIImageView *)imageView andFrame:(CGRect)frame
{
self.image = imageView.image;
self.imageView = imageView;
return [self initWithFrame:frame];
}
- (id)initWithImage:(UIImage *)image andFrame:(CGRect)frame
{
self.image = image;
self.imageView = [[UIImageView alloc] initWithImage:self.image];
return [self initWithFrame:frame];
}
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
- (void)scrollViewDidZoom:(UIScrollView *)sv
{
UIView* zoomView = [sv.delegate viewForZoomingInScrollView:sv];
CGRect zoomViewFrame = zoomView.frame;
if(zoomViewFrame.size.width < sv.bounds.size.width)
{
zoomViewFrame.origin.x = (sv.bounds.size.width - zoomViewFrame.size.width) / 2.0;
}
else
{
zoomViewFrame.origin.x = 0.0;
}
if(zoomViewFrame.size.height < sv.bounds.size.height)
{
zoomViewFrame.origin.y = (sv.bounds.size.height - zoomViewFrame.size.height) / 2.0;
}
else
{
zoomViewFrame.origin.y = 0.0;
}
zoomView.frame = zoomViewFrame;
}
- (void)scrollViewDoubleTapped:(UITapGestureRecognizer*)recognizer
{
if(self.zoomed==NO)
{
CGPoint pointInView = [recognizer locationInView:self.imageView];
CGSize scrollViewSize = self.scrollView.bounds.size;
CGFloat w = scrollViewSize.width / self.scrollView.maximumZoomScale;
CGFloat h = scrollViewSize.height / self.scrollView.maximumZoomScale;
CGFloat x = pointInView.x - (w / 2.0);
CGFloat y = pointInView.y - (h / 2.0);
CGRect rectToZoomTo = CGRectMake(x, y, w, h);
[self.scrollView zoomToRect:rectToZoomTo animated:YES];
self.zoomed = YES;
}
else if(self.zoomed == YES)
{
CGRect rectToZoomTo = CGRectMake(0, 0, self.scrollView.contentSize.width, self.scrollView.contentSize.height);
[self.scrollView zoomToRect:rectToZoomTo animated:YES];
self.zoomed = NO;
}
}
@end
It has something to do with the willAnimateToFrame method that is called when the viewController changes orientation. Any help would be greatly appreciated.
Got it working in case anyone is interested. I had to make some changes to my ImageZoom.m file:
#import "ImageZoom.h"
@interface ImageZoom ()
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIScrollView *scrollView;
@property BOOL zoomed;
@end
@implementation ImageZoom
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self loadContentWithFrame:frame];
}
return self;
}
-(void)loadContentWithFrame:(CGRect)frame
{
self.scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y, frame.size.width, frame.size.height)];
self.scrollView.delegate = self;
self.scrollView.contentSize = self.image.size;
self.backgroundColor = [UIColor redColor];
[self.scrollView addSubview:self.imageView];
[self addSubview:self.scrollView];
CGRect scrollViewFrame = self.scrollView.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / self.scrollView.contentSize.width;
CGFloat scaleHeight = scrollViewFrame.size.height / self.scrollView.contentSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
self.scrollView.minimumZoomScale = minScale;
self.scrollView.maximumZoomScale = 1;
self.scrollView.zoomScale = minScale;
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrollViewDoubleTapped:)];
doubleTapRecognizer.numberOfTapsRequired = 2;
doubleTapRecognizer.numberOfTouchesRequired = 1;
[self.scrollView addGestureRecognizer:doubleTapRecognizer];
self.zoomed = NO;
}
-(void)willAnimateToFrame:(CGRect)frame
{
self.frame = frame;
[self loadContentWithFrame:frame];
}
- (id)initWithImageView:(UIImageView *)imageView andFrame:(CGRect)frame
{
self.image = imageView.image;
self.imageView = imageView;
return [self initWithFrame:frame];
}
- (id)initWithImage:(UIImage *)image andFrame:(CGRect)frame
{
self.image = image;
self.imageView = [[UIImageView alloc] initWithImage:self.image];
return [self initWithFrame:frame];
}
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
- (void)scrollViewDidZoom:(UIScrollView *)sv
{
UIView* zoomView = [sv.delegate viewForZoomingInScrollView:sv];
CGRect zoomViewFrame = zoomView.frame;
if(zoomViewFrame.size.width < sv.bounds.size.width)
{
zoomViewFrame.origin.x = (sv.bounds.size.width - zoomViewFrame.size.width) / 2.0;
}
else
{
zoomViewFrame.origin.x = 0.0;
}
if(zoomViewFrame.size.height < sv.bounds.size.height)
{
zoomViewFrame.origin.y = (sv.bounds.size.height - zoomViewFrame.size.height) / 2.0;
}
else
{
zoomViewFrame.origin.y = 0.0;
}
zoomView.frame = zoomViewFrame;
}
- (void)scrollViewDoubleTapped:(UITapGestureRecognizer*)recognizer
{
if(self.zoomed==NO)
{
CGPoint pointInView = [recognizer locationInView:self.imageView];
CGSize scrollViewSize = self.scrollView.bounds.size;
CGFloat w = scrollViewSize.width / self.scrollView.maximumZoomScale;
CGFloat h = scrollViewSize.height / self.scrollView.maximumZoomScale;
CGFloat x = pointInView.x - (w / 2.0);
CGFloat y = pointInView.y - (h / 2.0);
CGRect rectToZoomTo = CGRectMake(x, y, w, h);
[self.scrollView zoomToRect:rectToZoomTo animated:YES];
self.zoomed = YES;
}
else if(self.zoomed == YES)
{
CGRect rectToZoomTo = CGRectMake(0, 0, self.scrollView.contentSize.width, self.scrollView.contentSize.height);
[self.scrollView zoomToRect:rectToZoomTo animated:YES];
self.zoomed = NO;
}
}
@end