三指捏合手势

6

我正在尝试实现三指捏合操作,但遇到了一些问题。

我之前使用的是两指捏合和两指旋转操作,分别执行(不需要或不希望同时手势),但问题是这两者非常相似,很多时候系统会识别错误的动作,因此我不得不移开手指再次按下,试图让系统识别旋转(通常它先识别捏合)。

我搜索了很多资料,想看看是否可以使用delayBegin或者激活同时手势等方法解决,但都没有成功。所以我的想法是,不再使用两个手指捏合,而是使用三个手指(因为捏合比旋转更容易)。

然而,问题在于,如你所知,捏合只能用两个手指完成。因此,我决定对UIPinchGestureReconizer进行子类化,并仅允许其在屏幕上放置三个手指时工作。其余部分可以像标准捏合操作一样工作,甚至忽略第三个手指(用于计算缩放比例),但必须确保第三个手指仍在屏幕上。

因此,我尝试了以下实现方式:ThreeFingerPinchRecognizer(它是UIPinchGestureRecognizer的子类)。

@implementation GRThreeFingerPinchRecognizer

-(id)initWithTarget:(id)target action:(SEL)action
    {
    self = [super initWithTarget:target action:action];
    if(self){
    }
    return self;
}

- (void)reset
{
    [super reset];
}

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    int numberOfTouches = event.allTouches.count;
    if (numberOfTouches == 3) 
     {
        [super touchesBegan:touches withEvent:event];
     }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    int numberOfTouches = event.allTouches.count;
    if (numberOfTouches == 3)
    {
        [super touchesMoved:touches withEvent:event];
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{ 
        [super touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesCancelled:touches withEvent:event];
 }

所以,正如您所看到的,我正在尝试通过仅调用[super]函数来获得2指捏合的相同功能,并在touchesBegantouchesMoved函数中测试屏幕上是否有3个手指(通过查看event.alltouches.count)。
使用这种方法,旋转与两个手指完美配合,但是捏合不太容易激活,而且即使激活了,也不能像两个手指捏合一样工作...
我知道我可能做错了,所以任何帮助都会很好!
非常感谢!

有趣的方法,但 (最终你调用的) PinchGestureRecognizer 可能期望2个触摸而不是3个,我建议在调用super之前尝试删除其中一个触摸.. 但你需要找出要删除哪一个触摸.. - Daniel
我认为这是在PinchGesture内部处理的,因为我没有改变传递的事件,只是将其转发!如果我删除“if”,捏合手势就可以正常工作(但需要2个手指)。 - Plauto Abreu
一个好的提示:对于启用了设置中缩放功能(这是一项苹果功能,在任何应用程序中双击屏幕三个手指可以放大屏幕,就像截图功能在任何应用程序中工作一样)的用户设备,三指手势功能将无法使用... 使用三指检测应用程序功能可能会像使用Home键检测功能一样具有致命性。(我和许多人都启用了这个缩放功能) - Albert Renshaw
为什么不创建自己的UIGestureRecognizer子类,实际检查2个手指的移动,然后相应地选择手势?随着手指的移动,捏合手势应该将触摸保持在原始2点的段内或接近其附近。另一方面,旋转应将它们显着移开。 - Rikkles
你能不能不用两个手指捏住,而是用一个手指移动来进行旋转? - ader
1个回答

0

查看此代码片段可以帮助您识别捏合手势的状态:

if (pinch.numberOfTouches > 1)
{
    CGPoint firstPoint = [pinch locationOfTouch:0 inView:self];
    CGPoint secPoint = [pinch locationOfTouch:1 inView:self];
    currentUpperY = MIN(firstPoint.y, secPoint.y);
    if (previousY == 0) previousY = currentUpperY;
    Float32 y = (self.contentOffset.y + previousY - currentUpperY);
    [self setContentOffset:CGPointMake(0, y < 0 ? 0 : y) animated:NO];

    if (pinch.state == UIGestureRecognizerStateBegan)
    {
        pinchStarted = YES;
        firstY = MIN(firstPoint.y, secPoint.y);
        secondY = MAX(firstPoint.y, secPoint.y);
        NSArray *pinchedIndexs = [self indexPathsForRowsInRect:CGRectMake(0.0, firstY, CGRectGetWidth(self.bounds), secondY)];
        if (pinchedIndexs.count) itemToOpenOrClose = [[currentItems subarrayWithRange:NSMakeRange(((NSIndexPath *)[pinchedIndexs objectAtIndex:0]).row, pinchedIndexs.count - 1)] copy];
    }
}

if ((pinch.state == UIGestureRecognizerStateChanged && pinchStarted && itemToOpenOrClose.count)
    || pinch.state == UIGestureRecognizerStateEnded)
{
    if (pinch.scale > 1) // Pinch OUT
    {
        for (Item *item in itemToOpenOrClose)
        {                
            [self openItem:item inIndexPath:[NSIndexPath indexPathForRow:[currentItems indexOfObject:item] inSection:0]];
        }
    }
    else if (pinch.scale < 1) // Pinch IN
    {
        for (Item *item in itemToOpenOrClose)
        {
            [self closeItem:item inIndexPath:[NSIndexPath indexPathForRow:[currentItems indexOfObject:item] inSection:0]];
        }
    }

    if (pinch.state == UIGestureRecognizerStateEnded)
    {
        pinchStarted = NO;
        itemToOpenOrClose = nil;
        previousY = 0;
    }
}

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