【问题标题】:UITapGestureRecognizer - single tap and double tapUITapGestureRecognizer - 单击和双击
【发布时间】:2012-02-11 04:03:58
【问题描述】:

我正在尝试将 2 个UITapGestureRecognizers 添加到视图中,一个用于单击,一个用于双击事件。单击识别器按预期工作(单独)。但我似乎无法让双击识别器工作。

已尝试尝试以下属性:cancelsTouchesInViewdelaysTouchesBegandelaysTouchesEnded,但仍然无法正常工作。

当我双击时,单击识别器将始终被激活,并且双击事件也将被发送到超级视图。但是自定义双击识别器似乎根本没有收到通知。

文档似乎表明上述 3 个属性可用于此目的。但我只是不确定应该设置哪些值以及在哪个识别器上(单、双或两者)。希望熟悉这方面的人可以提供帮助。

以下是最新更新的代码块。

// ****** gesture recognizers ******

- (void)addSingleAndDoubleTapGestureRecognizersToView:(UIView *)view
{
    // single tap    
    UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: tableViewController action: @selector(handleSingleTapOnView:)];                                 
    [singleTapRecognizer setNumberOfTouchesRequired:1];
    [view addGestureRecognizer: singleTapRecognizer];

    // double tap 
    UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: tableViewController action: @selector (handleDoubleTapOnView:)];        
    [doubleTapRecognizer setNumberOfTouchesRequired:2];         
    [singleTapRecognizer requireGestureRecognizerToFail: doubleTapRecognizer];
    [view addGestureRecognizer: doubleTapRecognizer];         
}

- (void)handleSingleTapOnView:(id)sender
{

}

- (void)handleDoubleTapOnView:(id)sender
{

}

【问题讨论】:

  • 随机注释:变量名中的下划线会让大多数 Objective-C 程序员畏缩。更糟糕的是你的变量名不是描述性的。为什么不直接使用 singleTapRecognizer 和 doubleTapRecognizer(或类似的东西)?打字需要一秒钟的时间,但会使您的代码更具可读性。
  • 感谢您的建议,同意您的观点,变量名称应该更具描述性。但是这个特定的代码段还没有最终确定,将按照建议发布更精致和描述性的代码......
  • 如果其他人有类似的问题。我努力让双击和单击识别器快速协同工作(单击工作正常,但没有双击)。我使用情节提要将识别器拖到场景中。我的viewDidLoad中有处理程序和语句:singleTapRecognizer.requireGestureRecognizerToFail(doubleTabRecognizer),但仍然没有双击。我缺少的难题是将双击识别器图标(从场景的顶行)拖动到要识别双击的视图部分。
  • @UIAdam 在 objc 中使用下划线作为私有 ivar 名称的前缀是相当普遍的,但不是吗? (来自 swift 背景)

标签: ios iphone uigesturerecognizer uitapgesturerecognizer


【解决方案1】:

您需要使用 requireGestureRecognizerToFail: 方法。像这样的:

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];

【讨论】:

  • 刚才再次尝试对两个识别器使用“失败”方法调用。但还是不行。如果您之前有过双击操作,请与我分享更多您的经验。
  • 我已经尝试过这个确切的代码(与 Anil 发布的更详细的代码相同),它对我有用。
  • 感谢您的评论,那么我肯定还有一些我错过的东西......
  • 您的代码仍然与 delaysTouches 和诸如此类的东西混为一谈。使它完全遵循 Anil 的代码。仅按我们的方式使用 requireGestureRecognizerToFail 一次。
  • 今天晚些时候或明天会按照你的建议去做,因为我现在时间不多了。感谢您的友好帮助...
【解决方案2】:
UITapGestureRecognizer *singleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSingleTap)] autorelease];
singleTap.numberOfTapsRequired = 1; 
[self.view addGestureRecognizer:singleTap];

UITapGestureRecognizer *doubleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doDoubleTap)] autorelease];
doubleTap.numberOfTapsRequired = 2; 
[self.view addGestureRecognizer:doubleTap];

[singleTap requireGestureRecognizerToFail:doubleTap];

注意: 如果你正在使用 numberOfTouchesRequired 它必须是 .numberOfTouchesRequired = 1;

对于斯威夫特

let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didPressPartButton))
singleTapGesture.numberOfTapsRequired = 1
view.addGestureRecognizer(singleTapGesture)

let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap))
doubleTapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTapGesture)

singleTapGesture.require(toFail: doubleTapGesture)

【讨论】:

  • 感谢您的回答,已尝试您的代码,但仍然无法正常工作。一定还有什么我错过的。你还有什么提示吗?
  • @Stanley:Anils 答案应该可以工作,当然你还必须提供处理程序(doSingleTap、doDoubleTap)
  • 单击更新 UITableView,它按预期工作。双击,暂时只是使用 NSLog 输出一条日志语句。我的怀疑是,在第一次点击后,第一响应者的状态会从 UIView 转到其他地方,因为我没有明确地对响应链做任何事情。
  • @Anil 提供的解决方案确实有效。就我而言,一些超级视图可能会阻止双击,同时让单击通过...
  • 该解决方案对我有用。单击选择器会在一些延迟后触发。
【解决方案3】:

不确定这是否正是您要寻找的,但我在没有手势识别器的情况下进行了单击/双击。我在 UITableView 中使用它,所以我在 didSelectRowAtIndexPath 方法中使用了该代码

    tapCount++;
    switch (tapCount)
    {
        case 1: //single tap
            [self performSelector:@selector(singleTap:) withObject: indexPath afterDelay: 0.2];
            break;
        case 2: //double tap
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTap:) object:indexPath];
            [self performSelector:@selector(doubleTap:) withObject: indexPath];
            break;
        default:
            break;
    }
    if (tapCount>2) tapCount=0;

方法 singleTap 和 doubleTap 只是 void 与 NSIndexPath 作为参数:

- (void)singleTap:(NSIndexPath *)indexPath {
  //do your stuff for a single tap
}

- (void)doubleTap:(NSIndexPath *)indexPath {
  //do your stuff for a double tap
}

希望对你有帮助

【讨论】:

  • 感谢@Novarg 的回答。您是否遇到过关于 doubleTap 识别器的问题?
  • @Stanley 不,singleTap 在触发前等待 0.2 秒。如果同时激活了第二次点击,则取消 singleTap 方法。
  • 看起来很有希望,感谢您的帮助。今天又没时间了。明天一定会试一试:)
  • 创意答案 ;)
  • 非常好的解决方案。我只需要在每个处理程序(singleTap、doubleTap)上添加 tapCount=0 以确保也能识别后续触摸。
【解决方案4】:

//----首先你必须分配双击和单击手势-------//

UITapGestureRecognizer* doubleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : @selector (handleDoubleTap:)];

UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : @selector (handleSingleTap:)];

[singleTap requireGestureRecognizerToFail : doubleTap];
[doubleTap setDelaysTouchesBegan : YES];
[singleTap setDelaysTouchesBegan : YES];

//-----------------------点击次数----------------//

[doubleTap setNumberOfTapsRequired : 2];
[singleTap setNumberOfTapsRequired : 1];

//-------在视图或按钮上添加双击和单击手势--------//

[self.view addGestureRecognizer : doubleTap];
[self.view addGestureRecognizer : singleTap];

【讨论】:

    【解决方案5】:

    一些视图有自己的内置双击识别器(MKMapView 就是一个例子)。要解决这个问题,您需要实现UIGestureRecognizerDelegate 方法shouldRecognizeSimultaneouslyWithGestureRecognizer 并返回YES

    首先实现你的双识别器和单识别器:

    // setup gesture recognizers
    UITapGestureRecognizer* singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                    action:@selector(mapViewTapped:)];
    singleTapRecognizer.delegate = self;
    singleTapRecognizer.numberOfTapsRequired = 1;
    
    
    UITapGestureRecognizer* doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                          action:@selector(mapViewDoubleTapped:)];
    doubleTapRecognizer.delegate = self;    // this allows
    doubleTapRecognizer.numberOfTapsRequired = 2;
    [singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
    

    然后执行:

    #pragma mark UIGestureRecognizerDelegate
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer
    *)otherGestureRecognizer {  return YES; }
    

    【讨论】:

      【解决方案6】:

      参考@stanley 的评论 -

      不要尝试使用轻击手势来选择行以在 UITableView 中工作,因为它已经具有完整的轻击处理......

      但您必须在单击手势识别器上将“取消视图中的触摸”设置为“否”,否则它将永远无法获得点击事件。

      【讨论】:

        【解决方案7】:

        Swift 2 的解决方案:

        let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
        singleTapGesture.numberOfTapsRequired = 1 // Optional for single tap
        view.addGestureRecognizer(singleTapGesture)
        
        let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
        doubleTapGesture.numberOfTapsRequired = 2
        view.addGestureRecognizer(doubleTapGesture)
        
        singleTapGesture.requireGestureRecognizerToFail(doubleTapGesture)
        

        【讨论】:

          【解决方案8】:

          Swift 3 解决方案:

          let singleTap = UITapGestureRecognizer(target: self, action:#selector(self.singleTapAction(_:)))
          singleTap.numberOfTapsRequired = 1
          view.addGestureRecognizer(singleTap)
          
          let doubleTap = UITapGestureRecognizer(target: self, action:#selector(self.doubleTapAction(_:)))
          doubleTap.numberOfTapsRequired = 2
          view.addGestureRecognizer(doubleTap)
          
          singleTap.require(toFail: doubleTap)
          

          在代码行 singleTap.require(toFail: doubleTap) 我们强制单击等待并确保点击事件不是双击。

          【讨论】:

            【解决方案9】:

            我实现了 UIGestureRecognizerDelegate 方法来检测 singleTap 和 doubleTap。

            就这样做吧。

             UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTapGesture:)];
                [doubleTap setDelegate:self];
                doubleTap.numberOfTapsRequired = 2;
                [self.headerView addGestureRecognizer:doubleTap];
            
                UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleSingleTapGesture:)];
                singleTap.numberOfTapsRequired = 1;
                [singleTap setDelegate:self];
                [doubleTap setDelaysTouchesBegan:YES];
                [singleTap setDelaysTouchesBegan:YES];
                [singleTap requireGestureRecognizerToFail:doubleTap];
                [self.headerView addGestureRecognizer:singleTap];
            

            然后实现这些委托方法。

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-10-08
              • 1970-01-01
              • 1970-01-01
              • 2021-09-03
              • 1970-01-01
              相关资源
              最近更新 更多