I'm able to use UIPinchGestureRecognizer
for making zoom in the View of a UICollectionViewCell
, but it doesn't matter the place where you start to make the UIPinch
gesture, always the zoom goes in the center of the view. For example, I would like to make pinch in the upper-left area of the view, and the zoom have to be created in the position where I touch the screen. But If I do that, the zoom is created in the center of the view.
This is the code I use for making zoom:
if([gesture state] == UIGestureRecognizerStateBegan) {
previousScale = 1.0;
}
if (
[gesture state] == UIGestureRecognizerStateChanged) {
CGFloat currentScale = [[[gesture view].layer valueForKeyPath:@"transform.scale"] floatValue];
// Constants to adjust the max/min values of zoom
const CGFloat kMaxScale = 4.0;
const CGFloat kMinScale = 1.0;
CGFloat newScale = 1 - (previousScale - [gesture scale]); // new scale is in the range (0-1)
newScale = MIN(newScale, kMaxScale / currentScale);
newScale = MAX(newScale, kMinScale / currentScale);
scale = newScale;
CGAffineTransform transform = CGAffineTransformScale([[gesture view] transform], newScale, newScale);
[gesture view].transform = transform;
[self.collectionView.collectionViewLayout invalidateLayout];
}
So how can I select the position of the UIPinchGesture?
Thanks
You are only applying the scale transform which will always keep the view at the center. Apart from scaling, you also have to perform translation based on the sender's locationInView
. You can replace the above function with the following code:
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
lastScale = 1.0;
lastPoint = [sender locationInView:self];
}
// Scale
CGFloat scale = 1.0 - (lastScale - sender.scale);
[self.layer setAffineTransform:
CGAffineTransformScale([self.layer affineTransform],
scale,
scale)];
lastScale = sender.scale;
// Translate
CGPoint point = [sender locationInView:self];
[self.layer setAffineTransform:
CGAffineTransformTranslate([self.layer affineTransform],
point.x - lastPoint.x,
point.y - lastPoint.y)];
lastPoint = [sender locationInView:self];
}
I did it, this is my final code:
if([gesture state] == UIGestureRecognizerStateBegan) {
previousScale = 1.0;
lastPoint = [gesture locationInView:[gesture view]];
}
if (
[gesture state] == UIGestureRecognizerStateChanged) {
CGFloat currentScale = [[[gesture view].layer valueForKeyPath:@"transform.scale"] floatValue];
// Constants to adjust the max/min values of zoom
const CGFloat kMaxScale = 4.0;
const CGFloat kMinScale = 1.0;
CGFloat newScale = 1 - (previousScale - [gesture scale]); // new scale is in the range (0-1)
newScale = MIN(newScale, kMaxScale / currentScale);
newScale = MAX(newScale, kMinScale / currentScale);
scale = newScale;
CGAffineTransform transform = CGAffineTransformScale([[gesture view] transform], newScale, newScale);
[gesture view].transform = transform;
CGPoint point = [gesture locationInView:[gesture view]];
CGAffineTransform transformTranslate = CGAffineTransformTranslate([[gesture view] transform], point.x-lastPoint.x, point.y-lastPoint.y);
[gesture view].transform = transformTranslate;
}