UIPinchGestureRecognizer将被捏住的视图放置在两个手指之间。

40

我已经成功地实现了一个视图的捏合缩放,但是该视图并没有定位到我希望它的位置。对于使用iPad的stackoverflowers,我希望我的视图能够像iPad Photos.app一样居中:当您对相册进行捏合和缩放时,照片呈现在一个不断扩大的视图中。该视图大约以第一个手指的右上角和另一个手指的左下角为中心。我将其与平移识别器混合在一起,但这样用户总是需要首先捏合,然后再平移来进行调整。

以下是一些图片说明,如果不清楚的话,我可以发布我的应用程序视频(并非秘密,我正在尝试复制iPad的Photos.app...)

因此,对于手指的初始位置,开始缩放:

输入图像描述

这是目前的“缩放”框架。正方形更大了,但位置却在手指下面

给定初始位置

这是我想要的结果:大小相同,但origin.x和y不同:

输入图像描述

(对于我的糟糕的Photoshop技能我感到抱歉^^)


嗨,Thomas,我也对此非常感兴趣。你找到任何解决方案了吗?你有任何示例代码吗?谢谢~ - ludo
2
我还没有时间回到这个问题,但是@md_develop的答案看起来很棒。我会尽力找时间更新我的代码,并在这个方法可行时接受这个答案。 - Thomas Joulin
2个回答

44

handlingPinchGesture方法中,您可以通过以下代码获取两个手指之间的中心点CGPoint

CGPoint point = [sender locationInView:self];

下面是我的完整handlePinchGesture方法:

/*
instance variables

CGFloat lastScale;
CGPoint lastPoint;
*/

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)sender {
    if ([sender numberOfTouches] < 2)
        return;

    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];
}

1
当[sender locationInView:self]始终返回两个捏合手指之间的中点时,这怎么可能起作用呢? - Guy
1
@Guy 在 UIGestureRecognizerStateBegan 之后,中点会因为你将手指移开或靠近而改变。locationInView:self 返回两个手指之间的质心。这部分是有效的。尽管经过1小时,我仍然无法在我的应用程序中使其正常工作,因为我需要移动一堆图层。 - Martin Berger
1
我使用了这种方法,视图已经被正确翻译。然而,它的翻译方式不像照片应用程序那样流畅。 - Tien Nguyen
@mishimay 如果我添加一个名为_myLayer的子层,并将你代码中的self.layer替换为_myLayer,那么你的代码将无法正确运行。这是为什么?如何修复它?提前致谢。 - Grey

11

看一下Touches示例项目。特别是这些方法可能会帮到你:


// scale and rotation transforms are applied relative to the layer's anchor point
// this method moves a gesture recognizer's view's anchor point between the user's fingers
- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        UIView *piece = gestureRecognizer.view;
        CGPoint locationInView = [gestureRecognizer locationInView:piece];
        CGPoint locationInSuperview = [gestureRecognizer locationInView:piece.superview];

        piece.layer.anchorPoint = CGPointMake(locationInView.x / piece.bounds.size.width, locationInView.y / piece.bounds.size.height);
        piece.center = locationInSuperview;
    }
}

// scale the piece by the current scale
// reset the gesture recognizer's rotation to 0 after applying so the next callback is a delta from the current scale
- (void)scalePiece:(UIPinchGestureRecognizer *)gestureRecognizer
{
    [self adjustAnchorPointForGestureRecognizer:gestureRecognizer];

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
        [gestureRecognizer view].transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
        [gestureRecognizer setScale:1];
    }
}

谢谢,但使用view.transform会同时调整我的子视图大小...有没有办法防止这种情况发生? - Thomas Joulin
#import <QuartzCore/QuartzCore.h> - 我需要这个来设置 anchorPoint。 - Jake Graham Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接