【问题标题】:iPhone iOS how to add a UILongPressGestureRecognizer and UITapGestureRecognizer to the same control and prevent conflict?iPhone iOS如何将UILongPressGestureRecognizer和UITapGestureRecognizer添加到同一个控件并防止冲突?
【发布时间】:2012-04-01 11:40:31
【问题描述】:

我正在构建一个 iPhone 应用程序,它可以让用户重新排列屏幕上的一些 UI 元素。

如何将点击手势识别器和长按手势识别器添加到同一个 UIView?当我从长按中抬起手指时,点击手势识别器会触发。如何在用户执行长按时暂时禁用轻击手势识别器或阻止它触发?

谢谢!

【问题讨论】:

    标签: iphone ios uiview uitapgesturerecognizer long-press


    【解决方案1】:

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

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

    3º 在源文件中添加回调:

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

    【讨论】:

      【解决方案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 
          }
      }
      

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

      【讨论】:

        【解决方案3】:

        作为替代方法,不要有两个单独的识别器 - 只需对两个事件都使用 LongPress 识别器:

        配置如下:

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

        【讨论】:

        • @Softlion 不要忘记 .h 文件上的 UIGestureRecognizerDelegate 接口 :-)
        • 它可以编译并运行,但不能防止冲突。我使用 2 个识别器和 gestureRecognizer(_:shouldRecognizeSimultaneouslyWithGestureRecognizer:) 解决了这个问题
        【解决方案4】:

        要让两种手势协同工作,请实现以下委托方法:

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

        要使长按优先,请执行以下操作:

        [tapGesture requireGestureRecognizerToFail:longPress];

        【讨论】:

        • 脱帽致敬。很好的答案。
        • 脱帽致敬。这最后一行代码就是我需要的。
        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-14
          • 1970-01-01
          • 2012-02-18
          • 2012-05-16
          • 1970-01-01
          • 1970-01-01
          • 2012-12-02
          相关资源
          最近更新 更多