如何识别oneTap/doubleTap?

bit*_*com 10 iphone uigesturerecognizer

我知道使用Apple API过滤oneTap/doubleTap.代码如下.

UITapGestureRecognizer *doubleTapGestureRecognizer = [[UITapGestureRecognizer alloc]
                        initWithTarget:self action:@selector(handleDoubleTap:)];
doubleTapGestureRecognizer.numberOfTapsRequired = 2;


[self addGestureRecognizer:doubleTapGestureRecognizer];


UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
singleTapGestureRecognizer.numberOfTapsRequired = 1;

**[singleTapGestureRecognizer requireGestureRecognizerToFail: doubleTapGestureRecognizer];**

[self addGestureRecognizer:singleTapGestureRecognizer];
Run Code Online (Sandbox Code Playgroud)

但oneTap/doubleTap checkDelayTime感觉如此之长(约0.5秒?).一般来说App的用户反应非常快.虽然0.5秒通常是短时间.但在移动设备环境中是长期的,因为用户的反应非常重要.

说到这一点,YouTubeApp在此输入图像描述有一个非常完美的算法,关于oneTap/doubleTap时刻的过滤.oneTap-doubleTap checkDelay是VeryVeryShort完美优化.

oneTap(show/hidden controlBar)

doubleTap(完整/默认videoScreenSize)

如何实现像YoutubeApp?关于oneTap-doubleTap过滤不使用requireGestureRecognizerToFail选择器.关于非常短的延迟oneTap-doubleTap区分.

我认为YoutubeApp不使用requireGestureRecognizer选择器.

ela*_*leb 22

最容易做到这一点的方法是继承UITapGestureRecognizer,而不是一般的UIGestureRecognizer.

像这样:

#import <UIKit/UIGestureRecognizerSubclass.h>

#define UISHORT_TAP_MAX_DELAY 0.2
@interface UIShortTapGestureRecognizer : UITapGestureRecognizer

@end
Run Code Online (Sandbox Code Playgroud)

并简单地实施:

@implementation UIShortTapGestureRecognizer

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(UISHORT_TAP_MAX_DELAY * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
    {
        // Enough time has passed and the gesture was not recognized -> It has failed.
        if  (self.state != UIGestureRecognizerStateRecognized)
        {
            self.state = UIGestureRecognizerStateFailed;
        }
    });
}
@end
Run Code Online (Sandbox Code Playgroud)

  • @bcattle 这里没有泄漏。该块不是由 self 保留的,而是由 dispatch_after 方法保留的。 (2认同)

Wal*_*ter 15

没有手势识别器,这是最容易做到的.然后你可以控制延迟.下面的代码是Apple在我的一个项目中使用的原始文档的变体.我的博客文章也谈到了它.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
 UITouch *touch = [touches anyObject];
if (touch.tapCount == 2) {
//This will cancel the singleTap action
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
 UITouch *touch = [touches anyObject];
if (touch.tapCount == 1) {
  //if they tapped within the coin then place the single tap action to fire after a delay of 0.3
  if (CGRectContainsPoint(coin.frame,[touch locationInView:self.view])){
    //this is the single tap action being set on a delay
  [self performSelector:@selector(onFlip) withObject:nil afterDelay:0.3];
  }else{
   //I change the background image here
  }
 } else if (touch.tapCount == 2) {
  //this is the double tap action
  [theCoin changeCoin:coin];
 }
}
Run Code Online (Sandbox Code Playgroud)


Ton*_*min 13

您需要做的只是添加额外的代码行以使用requireGestureRecognizerToFail

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
Run Code Online (Sandbox Code Playgroud)

然后整个代码成为:

UITapGestureRecognizer *doubleTapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(beginComicTransitions:)] autorelease];    
doubleTapRecognizer.numberOfTapsRequired = 2;
doubleTapRecognizer.numberOfTouchesRequired = 1;
doubleTapRecognizer.delegate = self;   

UITapGestureRecognizer *singleTapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(bringMenu:)] autorelease];    
singleTapRecognizer.numberOfTapsRequired = 1;
singleTapRecognizer.numberOfTouchesRequired = 1;
singleTapRecognizer.delegate = self;

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
Run Code Online (Sandbox Code Playgroud)

requireGestureRecognizerToFail意味着:

  • 如果未识别双击,则单击即可识别
  • 如果识别出双击,则无法识别单击

swift版本代码是:

    let doubleTap = UITapGestureRecognizer(target: self, action: "doubleTapped:")
    doubleTap.numberOfTapsRequired = 2
    doubleTap.numberOfTouchesRequired = 1
    self.scrollView.addGestureRecognizer(doubleTap)

    let singleTap = UITapGestureRecognizer(target: self, action: "singleTap:")
    singleTap.numberOfTapsRequired = 1
    singleTap.numberOfTouchesRequired = 1
    self.scrollView.addGestureRecognizer(singleTap)

    singleTap.requireGestureRecognizerToFail(doubleTap)
Run Code Online (Sandbox Code Playgroud)