Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to recognize oneTap/doubleTap at moment?

I Know filtering oneTap/doubleTap using a Apple API. code are follows.

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

but oneTap/doubleTap checkDelayTime is feeling a so Long (About 0.5sec?). Generally App Users of the reaction is very fast. Although 0.5 seconds is typically short-time. but In Mobile Device Environment is long-time, because users react is very important.

Speaking to the point, YouTubeAppenter image description here have a very Perfectly algorithm about filtering at a moment oneTap/doubleTap. oneTap-doubleTap checkDelay is VeryVeryShort Perfectly Optimization.

oneTap(show/hidden controlBar)

doubleTap(full/default videoScreenSize)

How to implement like YoutubeApp? about oneTap-doubleTap filtering Not Using a requireGestureRecognizerToFail Selector. about very short delay oneTap-doubleTap distinguishing.

I think YoutubeApp is Not Use a requireGestureRecognizer Selector.

like image 901
bitmapdata.com Avatar asked Nov 08 '11 14:11

bitmapdata.com


3 Answers

This is easiest to do without gesture recognizers. Then you can control the delay. The code below is a variation of Apple's original documentation that I use in one of my projects. I have blog post that talks about it as well.

- (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];
 }
}
like image 149
Walter Avatar answered Sep 29 '22 13:09

Walter


only thing you need to do is add extra line of code to use requireGestureRecognizerToFail

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];

then whole code become to:

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

here's requireGestureRecognizerToFail means:

  • if not recognized double tap, then single tap be recognized
  • if recognized double tap, will not recognize single tap

swift version code is:

    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)
like image 45
Toncean Cosmin Avatar answered Sep 29 '22 13:09

Toncean Cosmin


The easiest way to do this is to subclass UITapGestureRecognizer and not a general UIGestureRecognizer.

Like this:

#import <UIKit/UIGestureRecognizerSubclass.h>

#define UISHORT_TAP_MAX_DELAY 0.2
@interface UIShortTapGestureRecognizer : UITapGestureRecognizer

@end

And simply implement:

@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
like image 34
eladleb Avatar answered Sep 29 '22 11:09

eladleb