iPhone iOS如何将UILongPressGestureRecognizer和UITapGestureRecognizer添加到同一个控件并避免冲突?

22
我正在开发一款 iPhone 应用程序,用户可以重新排列屏幕上的一些 UI 元素。
如何为同一个 UIView 添加轻击手势识别器和长按手势识别器?当用户从长按手势中抬起手指时,会触发轻击手势识别器。如何暂时禁用轻击手势识别器或防止它在用户执行长按操作时触发?
谢谢!
5个回答

56
为了让两种手势能够同时使用,请实现以下委托方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

要使长按手势具有优先级,执行以下操作:

[tapGesture requireGestureRecognizerToFail:longPress];


脱帽致敬,回答很好。 - Abdul Yasin
脱帽致敬。这是我需要的最后一行代码。 - dellos

11

要成功地结合两者,您需要:

1. 在头部添加手势委托的接口。

@interface ViewController : ViewController <UIGestureRecognizerDelegate>

2º 创建手势事件并将其添加到源文件中的视图:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touch:)];
    [tap setNumberOfTapsRequired:1]; // Set your own number here
    [tap setDelegate:self]; // Add the <UIGestureRecognizerDelegate> protocol

    UILongPressGestureRecognizer *longTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longTouch:)];
    [longTap setNumberOfTapsRequired:0]; // Set your own number here
    [longTap setMinimumPressDuration:1.0];
    [longTap setDelegate:self]; // Add the <UIGestureRecognizerDelegate> protocol
    [tap requireGestureRecognizerToFail:longTap];   // Priority long

    [self.view addGestureRecognizer:tap];
    [self.view addGestureRecognizer:longTap];

第三步,在源文件中添加回调函数:

- (void) touch: (UITapGestureRecognizer *)recognizer
{
    CGPoint location = [recognizer locationInView: self.HUDview];
    if (recognizer.state == UIGestureRecognizerStateBegan)
    {
        NSLog(@"touch UIGestureRecognizerStateBegan");
    }
    if (recognizer.state == UIGestureRecognizerStateEnded)
    {
        NSLog(@"touch UIGestureRecognizerStateEnded");
        //NSLog(@"Position of touch: %.3f, %.3f", location.x, location.y);    // Position landscape
    }
}

- (void) longTouch: (UILongPressGestureRecognizer *)recognizer
{
    if (recognizer.state == UIGestureRecognizerStateBegan)
    {
        NSLog(@"longTouch UIGestureRecognizerStateBegan");
    }
    if (recognizer.state == UIGestureRecognizerStateEnded)
    {
        NSLog(@"longTouch UIGestureRecognizerStateEnded");
    }
}

4º设置手势识别器可用:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

8
作为另一种方法,不要使用两个独立的识别器,而是只使用长按识别器来处理这两种事件:
按以下方式进行配置:
UILongPressGestureRecognizer* longPress = [ [ UILongPressGestureRecognizer alloc ] initWithTarget:self.nextResponder action:@selector(longPressEvent:)];
    categoryPanelDrag.minimumPressDuration = 0.0;

然后按照以下步骤处理:
- (BOOL)longPressEvent:(UILongPressGestureRecognizer *)gesture {

    // _dragStarted is a class-level BOOL

    if(UIGestureRecognizerStateBegan == gesture.state) {
        _dragStarted = NO;
    }

    if(UIGestureRecognizerStateChanged == gesture.state) {
        _dragStarted = YES;
        // Do dragging stuff here
    }

    if(UIGestureRecognizerStateEnded == gesture.state) {

        if (_dragStarted == NO)
        {
            // Do tap stuff here

        }
        else
        {
            // Do drag ended stuff here
        }
    }

    return YES;

}

1
@Softlion 不要忘记在.h文件中添加UIGestureRecognizerDelegate接口 :-) - Avi Levin
编译和运行都没问题,但无法防止冲突。我使用了两个识别器和gestureRecognizer(_:shouldRecognizeSimultaneouslyWithGestureRecognizer:)方法解决了这个问题。 - Softlion

2

我尝试了Moby和Journeyman的方法,但它们似乎并不适合我的项目,所以我按照以下方式解决了问题:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
    NSLog(@"%@ %ld",touch.description, touch.phase);
    [self performSelector:@selector(checkTouch:) withObject:touch afterDelay:0.5];
    return YES;
}

而且
- (void)checkTouch:(UITouch *)touch{
    NSLog(@"touch phase = %ld",touch.phase);
    if (touch.phase == UITouchPhaseStationary) {
        //still holding my hand and this means I wanted longPressTouch
    }
    if (touch.phase == UITouchPhaseEnded){
        //I released my finger so it's obviously tap 
    }
}

这可能是一个更简单的解决方案,但当然这取决于项目。


0

你可以在代码中处理它,在长按期间设置一个标志,如果在标志为真或其他情况下调用了轻击,则不执行轻击代码并重置标志。我不知道更好的方法。


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