Limiting UIPinchGestureRecognizer Zoom Levels
Here is how to use a UIPinchGestureRecognizer and how to limit it's zoom levels on your custom views and content. My use case was for resizing images on a custom view. I wanted to prevent very large images and to prevent very small images. Very large images have a ton of pixilation and artifacts. While very small images are hard to touch and a user cannot do anything useful with them.
Basic Math
1. We know: currentSize * scaleFactor = newSize
2. Clamp the maximum scale factor using the proportion maxScale / currentScale
3. Clamp the minimum scale factor using the proportion minScale / currentScale
The code below assumes there is an instance variable CGFloat lastScale and that a view has been set for the UIPinchGestureRecognizer.
Sample Code
#import <QuartzCore/QuartzCore.h> // required for working with the view's layers
//....
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer {
if([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
// Reset the last scale, necessary if there are multiple objects with different scales
lastScale = [gestureRecognizer scale];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:@"transform.scale"] floatValue];
// Constants to adjust the max/min values of zoom
const CGFloat kMaxScale = 2.0;
const CGFloat kMinScale = 1.0;
CGFloat newScale = 1 - (lastScale - [gestureRecognizer scale]); // new scale is in the range (0-1)
newScale = MIN(newScale, kMaxScale / currentScale);
newScale = MAX(newScale, kMinScale / currentScale);
CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], newScale, newScale);
[gestureRecognizer view].transform = transform;
lastScale = [gestureRecognizer scale]; // Store the previous scale factor for the next pinch gesture call
}
}