Tuesday, March 24, 2009

Reset a UIScrollView

This has to be the most puzzling thing I've come across in iphone app building thus far. I wanted to "reset" a UIScrollView after pinch zooming and scrolling. It turns out, there is no way to reset the zoom factor on the contentView in a UIScrollView. At least not in the current SDK. You must completely replace the subview of the scroll view to work around it.

I wanted this transition to happen smoothly, so I used some core animation. Here is some working code to get the scroll view to "reset". In my app, I implemented this after a double tap, and after an orientation change.

self.scrollView is the UIScrollView, and self.imageView is the UIImageView subview.

- (void) resetImageZoom {

// animate the transition
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(resetAnimFinish:finished:context:)];
[UIView setAnimationDuration:0.4];

// reset the scrollview and the current image view
self.scrollView.transform = CGAffineTransformIdentity;
self.scrollView.contentOffset = CGPointZero;
self.imageView.frame = self.scrollView.frame;
self.imageView.center = self.scrollView.center;
self.scrollView.contentSize = self.imageView.frame.size;

[UIView commitAnimations];


-(void)resetAnimFinish:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {

// make a copy of the image view
UIImageView *copy = [[UIImageView alloc] initWithImage:self.imageView.image];
copy.autoresizingMask = self.imageView.autoresizingMask;
copy.contentMode = self.imageView.contentMode;
copy.frame = self.imageView.frame;
copy.center = self.imageView.center;

// replace the current image view with our copy
[self.imageView removeFromSuperview];
self.imageView = copy;
[self.scrollView addSubview:copy];
[copy release];

If you wanted, you could extend UIImageView an implement the NSCopying protocol, then just use the copy convenience method. I chose to copy the object a bit more manually here.


marika said...

Works great! Thank you for sharing the code.

Sarah Clough said...

I can't get this to work and I'm tearing my hair out. I've tried googling and all sorts of examples and yours seems to do what I want (in theory), however the scroll view still doesn't reset. The imageview shrinks and disappears up to the top left as the scrollview is still zoomed - you can see the little scroll bars when you pan around inside it. Any suggestions? Thanks.

Sarah Clough said...

Don't worry, I found a way round it without resetting the zoom.