I am going through the Sample code of iPhone WWDC 2010 - 104 PhotoScroller App. It\'s working great with my project related images (PDF Page Images)
but I am struggl
Subclass the UIScrollView an in m file add
#pragma mark -
#pragma mark doubleTouch
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
NSUInteger tapCount = [touch tapCount];
switch (tapCount) {
case 2:
{
if(self.zoomScale <1.0){
[self setZoomScale:1.0 animated:YES];
}else{
[self setZoomScale:0.1 animated:YES];
}
break;
}
default:
break;
}
}
Here is a Swift solution based on @possen's great answer.
- Put this in your view controller that contains the scrollview and is the scrollview delegate.
- This solution is great since it actually zooms to the tap location:
@IBAction func handleDoubleTapScrollView(recognizer: UITapGestureRecognizer) {
if scrollView.zoomScale == 1 {
scrollView.zoom(to: zoomRectForScale(scale: scrollView.maximumZoomScale, center: recognizer.location(in: recognizer.view)), animated: true)
} else {
scrollView.setZoomScale(1, animated: true)
}
}
func zoomRectForScale(scale: CGFloat, center: CGPoint) -> CGRect {
var zoomRect = CGRect.zero
zoomRect.size.height = imageView.frame.size.height / scale
zoomRect.size.width = imageView.frame.size.width / scale
let newCenter = scrollView.convert(center, from: imageView)
zoomRect.origin.x = newCenter.x - (zoomRect.size.width / 2.0)
zoomRect.origin.y = newCenter.y - (zoomRect.size.height / 2.0)
return zoomRect
}
I researched several different web sites and I came up with the following...
Place this code into your viewDidLoad or viewWillAppear method:
//////////////////////////////
// Listen for Double Tap Zoom
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.scrollView addGestureRecognizer:doubleTap];
[doubleTap release];
Add this to your header file:
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer;
Add this to your implementation:
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
if(self.scrollView.zoomScale > self.scrollView.minimumZoomScale)
[self.scrollView setZoomScale:self.scrollView.minimumZoomScale animated:YES];
else
[self.scrollView setZoomScale:self.scrollView.maximumZoomScale animated:YES];
}
Currently this does not center upon the area where the user double tapped.
My code, based upon some of the code at link "UIImageView does not zoom" This code handles toggling between zoomed in and zoomed out and will allow detection of a single tap along with a double tap. It also properly centers the zoom on the embedded image by applying the view transform on it. This code would go in the ImageScrollView class from the sample code.
- (void)setupGestureRecognisers:(UIView *)viewToAttach {
UITapGestureRecognizer *dblRecognizer;
dblRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleDoubleTapFrom:)];
[dblRecognizer setNumberOfTapsRequired:2];
[viewToAttach addGestureRecognizer:dblRecognizer];
self.doubleTapRecognizer = dblRecognizer;
UITapGestureRecognizer *recognizer;
recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleTapFrom:)];
[recognizer requireGestureRecognizerToFail:dblRecognizer];
[viewToAttach addGestureRecognizer:recognizer];
self.tapRecognizer = recognizer;
}
- (void)handleTapFrom:(UITapGestureRecognizer *)recognizer {
// do your single tap
}
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
zoomRect.size.height = [_imageView frame].size.height / scale;
zoomRect.size.width = [_imageView frame].size.width / scale;
center = [_imageView convertPoint:center fromView:self];
zoomRect.origin.x = center.x - ((zoomRect.size.width / 2.0));
zoomRect.origin.y = center.y - ((zoomRect.size.height / 2.0));
return zoomRect;
}
- (void)handleDoubleTapFrom:(UITapGestureRecognizer *)recognizer {
float newScale = [self zoomScale] * 4.0;
if (self.zoomScale > self.minimumZoomScale)
{
[self setZoomScale:self.minimumZoomScale animated:YES];
}
else
{
CGRect zoomRect = [self zoomRectForScale:newScale
withCenter:[recognizer locationInView:recognizer.view]];
[self zoomToRect:zoomRect animated:YES];
}
}
I combined the answers from @jayesh kavathiya and @possen into a single implementation which works pretty well, as long as you've set appropriate values for self.minimumZoomScale
and self.maximumZoomScale
.
- (void)doubleTap:(UITapGestureRecognizer*)recognizer
{
if (self.zoomScale > self.minimumZoomScale)
{
[self setZoomScale:self.minimumZoomScale animated:YES];
}
else
{
CGPoint touch = [recognizer locationInView:recognizer.view];
CGSize scrollViewSize = self.bounds.size;
CGFloat w = scrollViewSize.width / self.maximumZoomScale;
CGFloat h = scrollViewSize.height / self.maximumZoomScale;
CGFloat x = touch.x-(w/2.0);
CGFloat y = touch.y-(h/2.0);
CGRect rectTozoom=CGRectMake(x, y, w, h);
[self zoomToRect:rectTozoom animated:YES];
}
}
Zooms in on tap location
CGFloat scale = 3.0;
CGFloat scale = ScaleToAspectFitRectAroundRect(frame, self.bounds) * 2.0;
CGRect zoomRect;
CGPoint point = [gestureRecognizer locationOfTouch:0 inView:[gestureRecognizer view]];
zoomRect.size.height = frame.size.height * scale;
zoomRect.size.width = frame.size.width * scale;
zoomRect.origin.x = CGRectGetMidX(frame) - (CGRectGetWidth(zoomRect)/2) + (scale * (CGRectGetWidth(frame)/2 - point.x)) - (CGRectGetWidth(frame)/2 - point.x);
zoomRect.origin.y = CGRectGetMidY(frame) - (CGRectGetHeight(zoomRect)/2) + (scale * (CGRectGetHeight(frame)/2 - point.y)) - (CGRectGetHeight(frame)/2 - point.y);