Zooming to a point in UIScrollView
If there’s one piece of functionality that has become basically boilerplate on iOS, it’s the concept of double-tapping a zoomable UIScrollView to quickly zoom in on a given point. When I was writing the code for displaying pages in iComics, I assumed that this would be a really simple thing to do. I mean, surely all you’d need is a UITapGestureRecognizer attached to a UIScrollView that passes the location of any double-taps to the scroll view… right?
Turns out that although there is a UIScrollView method called ‘zoomToRect‘ (which lets you zoom to a specific CGRect region of a UIScrollView), out-of-the-box, there is no official way to procedurally zoom into a specific CGPoint. This actually surprised me greatly since I would have thought it would be a standard part of UIKit.
In any case, I did a bit of searching around on Google, looking for some code that would let me do this easily. I found a few bits of code here and there, however they were written in such a way that unless the minimum and maximum scales of the scroll view were set up in a specific way (Uh, which in iComics’ case, they weren’t), the zooming wouldn’t work properly at all.
So, cutting to the chase, I decided to just roll my own category for UIScrollView to add that functionality to it. All it does is take a CGPoint (relative to the bounds of the scroll view itself) and a scale, and translates those to a CGRect that can then be passed to UIScrollView’s drawToRect method.
Here’s what it looks like:
@implementation UIScrollView (ZoomToPoint)
- (void)zoomToPoint:(CGPoint)zoomPoint withScale: (CGFloat)scale animated: (BOOL)animated
{
//Normalize current content size back to content scale of 1.0f
CGSize contentSize;
contentSize.width = (self.contentSize.width / self.zoomScale);
contentSize.height = (self.contentSize.height / self.zoomScale);
//translate the zoom point to relative to the content rect
zoomPoint.x = (zoomPoint.x / self.bounds.size.width) * contentSize.width;
zoomPoint.y = (zoomPoint.y / self.bounds.size.height) * contentSize.height;
//derive the size of the region to zoom to
CGSize zoomSize;
zoomSize.width = self.bounds.size.width / scale;
zoomSize.height = self.bounds.size.height / scale;
//offset the zoom rect so the actual zoom point is in the middle of the rectangle
CGRect zoomRect;
zoomRect.origin.x = zoomPoint.x - zoomSize.width / 2.0f;
zoomRect.origin.y = zoomPoint.y - zoomSize.height / 2.0f;
zoomRect.size.width = zoomSize.width;
zoomRect.size.height = zoomSize.height;
//apply the resize
[self zoomToRect: zoomRect animated: animated];
}
@end
Looking at it, it should be pretty straightforward to figure out how it works. If you see anything wrong with it, let me know in the comments. As always, feel free to use this code in any of your projects, and let me know if you make anything awesome with it.
-
Andre
-
http://www.tim-oliver.com -=TiM=-
-
Cupcake
-
http://machindoapps.com/ Machindoapps
-
Example
-
http://www.facebook.com/profile.php?id=1027625283 Daniel Loughney
-
http://www.tim-oliver.com -=TiM=-
-