Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I cancel a UIScrollView zoom bounce?

I'm using a zooming UIScrollView to show images in my iPad app. The zooming works great, with a pinch making an image smaller or bigger as appropriate. I also have bouncesZoom enabled so that it bounces back to the minimum or maximum zoom if the user stretches it too far one way or the other.

Now I'd like to recognize when a pinch has ended with the image 10% smaller than the minimum zoom size and, in such a case, prevent the bounce from happening and trigger a different animation that shrinks the image to "close" it. This way, there can be a sort of "pinch to close" gesture. What I've come up with to do this, at its simplest, is this:

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    if (self.zoomBouncing && zoomedToScale / self.minimumZoomScale < 0.90) {
        // We've let go and were under 90% of the minimum size.
        self.minimumZoomScale = zoomedToScale;
        [self shrinkImageToNothing];
    } else {
        // How far have we gone?
        zoomedToScale = self.zoomScale;
    }
}

This works great, except that at this point it's already bouncing, so the setting of minimumZoomScale does nothing. Therefore, the bounce and shrink occur at the same time, which as you might imagine looks pretty weird.

So my question is: How can I prevent the bounce from happening only in this specific situation? There is no UIScrollViewDelegate method that allows my code to do something between when the gesture finishes and when the UIScrollView decides to bounce back. I've tried a bunch of other techniques with no luck, including:

  • Returning nil from –viewForZoomingInScrollView: when my 90% zoom threshold has been passed. Doesn't work because this method is called when the gesture begins, not for every point of the zoom.
  • Setting bouncesZoom in -scrollViewDidZoom: to false when the zoom factor is less than 90% and to true when it's greater than or equal to 90%. Makes the image shake badly when the scale gets under 90% because it disallows that size when the bouncesZoom is false.
  • Adding a -touchesEnded:withEvent method. It never gets called.
  • Adding my own UIPinchGestureRecognizer to execute concurrently with the UIScrollView's own pinch recognizer. Doesn't work because its handlers (and delegate methods) are called after UIScrollView's pinch gesture, which makes the decision to bounce before my gesture can tell it not too. I tried removing all the core gestures, adding mine, and adding the core gestures back. But my gesture was still called after UIScrollView had decided it was bouncing.

So I'm at a bit of a loss. Anyone else tried to do something like this?

like image 937
theory Avatar asked Mar 07 '11 06:03

theory


2 Answers

You have to simply set this property to NO. (ex. in ViewDidLoad)

scrollView.bouncesZoom = NO;

like image 140
torutoru Avatar answered Nov 18 '22 07:11

torutoru


I guess writing out this question helped me to get on the road to finding the solution. And fortunately, it's quite easy! So, first step, in the code I have that sets minimumZoomScale, I also set a cachedMinZoomScale ivar to the same value. With that, getting the bounce not to happen when the scale is less than 90% of the minimum is actually quite straight-forward:

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    if (self.zoomScale / cachedMinZoomScale < 0.90) {
        self.minimumZoomScale = self.zoomScale;
    } else {
        self.minimumZoomScale = cachedMinZoomScale;
    }
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
    if (self.zoomScale / cachedMinZoomScale < 0.90) {
        [self shrinkImageToNothing];
    }
}

Basically, when the scroll view zooms, keep the -self.minimumZoomScale at the current zoom scale if it's less than 90% of the actual minimum, but set it to that actual minimum at any other zoom scale. Then, when the zoom finishes, if we're under that 90% threshold, it won't snap back to anything because it will already be the minimum size, and then just call the new animation to shrink to close.

Simple. Phew!

like image 29
theory Avatar answered Nov 18 '22 07:11

theory