2

I'm using UIPinchGestureRecognizer in my app to zoom in on a view (and yes, there's a reason I'm not using UIScrollView). When I pinch outwards with my fingers, the view zooms in as expected, and if I then reverse pinch without taking my fingers off the screen, it also zooms right. However, if I initiate the zoom by pinching inwards, the rate at which the view zooms is dramatically slower. I'm guessing this is because of how UIPinchGestureRecognizer works - the scale of the UIPinchGestureRecognizer is >1 when pinching outwards, and <1 when pinching inwards. Unfortunately, I do not know how to accurately reflect this in my code.

- (IBAction)didDetectPinchGesture:(id)sender {
    UIPinchGestureRecognizer *gestureRecognizer = (UIPinchGestureRecognizer *)sender;

    CGFloat scale = [gestureRecognizer scale];

    switch ([gestureRecognizer state]) {
        case UIGestureRecognizerStateBegan:
            _lastScale = [gestureRecognizer scale];
            break;

        case UIGestureRecognizerStateChanged:

            CGFloat currentScale = [[self.imageView.layer valueForKeyPath:@"transform.scale"] floatValue];

            // Constants to adjust the max/min values of zoom
            const CGFloat kMaxScale = 5.0;
            const CGFloat kMinScale = 1.0;

            CGFloat newScale = 1 -  (_lastScale - scale); // new scale is in the range (0-1)
            newScale = MIN(newScale, kMaxScale / currentScale);
            newScale = MAX(newScale, kMinScale / currentScale);

            NSLog(@"%f", newScale);

            CGAffineTransform transform = CGAffineTransformScale([self.imageView transform], newScale, newScale);
            self.imageView.transform = transform;

            _lastScale = scale;  // Store the previous scale factor for the next pinch gesture call
            break;

        default:
            _lastScale = [gestureRecognizer scale];
            break;
    }
}
Riley Testut
  • 431
  • 1
  • 8
  • 22
  • There is a much easier way to do this actually. Set the transform according to the change in scale and then *reset the scale* of the gesture to 1 after you are done `gestureRecognizer.scale = 1.f;` ;) – borrrden Apr 04 '13 at 02:08
  • 2
    I don't know what is going on, that value is not readonly. I do exactly as I describe, and the docs also say that it is not readonly. Are you sure you didn't write something weird like `[gestureRecognizer scale] = 1.f`? That's more like what the message sounds like. @JohnRiselvato – borrrden Apr 04 '13 at 23:40
  • @borrrden I did as you said and as expected, the object vibrated back and forth because resetting it doesn't actually help the scale.. – John Riselvato Apr 05 '13 at 18:22

1 Answers1

-1

A very simple solution to this is to reset the gestureRecognizer scale back to 1 when you're finished:

    ...
    default:
        _lastScale = [gestureRecognizer scale];
        // Add this:
        [gestureRecognizer setScale:1];
        break;
    }
brandonscript
  • 68,675
  • 32
  • 163
  • 220