三指捏合手势

Posted

技术标签:

【中文标题】三指捏合手势【英文标题】:Three finger pinch gesture 【发布时间】:2012-12-08 13:51:34 【问题描述】:

我在尝试实现 3 指捏合时遇到了一些问题。

我一直在单独使用 2 指捏合和 2 指旋转! (不需要或不需要同时手势)问题是很多时候,系统识别出错误的动作,因为它们都非常相似,所以我最终不得不移开手指并再次按下以尝试让系统识别旋转(通常它首先识别夹点)

我搜索了很多以查看delayBegin 是否有帮助,或者我是否可以做一些激活同时手势的操作,但没有一个可以正常工作,所以我的想法是不要使用 2 根手指捏,我可以使用 3 (因为捏比旋转更容易)。

问题是,如您所知,Pinch 仅适用于 2 个手指。所以我决定我可以继承 UIPinchGestureReconizer 并且只允许它在屏幕上有 3 个手指时工作。其余的它可以像标准捏合一样工作,即使忽略无名指(计算比例)但确保无名指仍在屏幕上。

所以我为我的 ThreeFingerPinchRecognizer 尝试了以下实现(即 Sub 类 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] 函数,在 touchesBegantouchesMoved 函数中,我正在测试如果屏幕上有 3 个手指(通过查看 event.alltouches.count

有了这个,两根手指的旋转效果很好,但是捏的效果不是很好,很难激活它,当它激活时,它不能像两根手指捏一样工作......

我知道我可能做错了,所以任何帮助都会很棒!

非常感谢!

【问题讨论】:

有趣的方法,但 PinchGestureRecognizer (最后你正在调用它)可能期望 2 次触摸而不是 3 次,我可能会在你调用 super 之前尝试删除其中一个触摸......你要去必须弄清楚要删除哪个.. 我相信这是在 PinchGesture 内部处理的,因为我没有在事件通过时更改任何内容,我只是转发它!如果我删除“如果”,捏能正常工作(但用 2 个手指) *注意:3 指功能不适用于启用了缩放设置的用户设备(Apple 功能,您可以用 3 根手指双击屏幕进行放大(在任何应用程序中,很多就像屏幕截图功能在任何应用程序中的工作方式一样))...使用 3 更精细的应用程序功能检测可能与使用主页按钮检测功能一样致命。 (我和其他许多人都启用了此缩放功能) 您为什么不创建自己的 UIGestureRecognizer 子类并实际检查 2 个手指的移动,然后相应地选择手势?随着手指的移动,捏住应该使触摸保持在原始 2 点的段内,或接近它。另一方面,旋转应该将它们显着移开。 你能不能不用两根手指捏住,用一个手指移动来旋转? 【参考方案1】:

查看此片段可以帮助您识别捏合状态:

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;
    

【讨论】:

以上是关于三指捏合手势的主要内容,如果未能解决你的问题,请参考以下文章

如果视图注册平移手势,则捏合手势不起作用

同时检测捏合和旋转手势

捏合和点击手势无法正常工作

带有平移、旋转和捏合手势的 UIKit Dynamics

如何为 Android 测试生成缩放/捏合手势

TouchImageView 在捏合手势之后才显示图像