2013-10-01 14 views
12

Na przykład mam widoku, gdzie chcę dwa różne gesty:Jak wykrywać dotknięcie i podwójne dotknięcie jednocześnie za pomocą UITapGestureRecognizer?

dotknij, aby wykonać działanie A. dwukrotnie, aby wykonać działanie przyczyni B.

problem jest z UITapGestureRecognizer Mogę jedynie ustawić minimalny wymagany liczyć z kranu . Rozpoznawanie jednym dotknięciem rozpoznaje dotknięcie, zanim dwukrotne dotknięcie rozpoznawania gestów rozpozna podwójne dotknięcie.

Przykład:

_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognized:)]; 
_tapGestureRecognizer.numberOfTouchesRequired = 1; 
_tapGestureRecognizer.numberOfTapsRequired = 1; 
[self addGestureRecognizer:_tapGestureRecognizer]; 

_doubleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognized:)]; 
_doubleTapGestureRecognizer.numberOfTouchesRequired = 1; 
_doubleTapGestureRecognizer.numberOfTapsRequired = 2; 
[self addGestureRecognizer:_doubleTapGestureRecognizer]; 

Zawsze rozpoznaje jednego kranu, nawet jeśli robię podwójną kurek bardzo szybko. Jak mogę to skonfigurować, aby narzędzie do rozpoznawania gestów czekało i widzi, czy rozpoznaje go rozpoznawanie za pomocą dwukrotnego kliknięcia?

+0

Możliwe rozwiązanie i powielone: ​​http://stackoverflow.com/questions/7175086/iphone-single-tap-gesture-conflicts-with-double-one – xarly

+0

Spróbuj usunąć opóźnienie lub dopasować, do którego chcesz. http://stackoverflow.com/a/25368653/3060790 – Pagly

Odpowiedz

42

Oto, czego użyłem w jednym z moich starych projektów, mam nadzieję, że pomoże ci w człowieku.

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

Idealny! Dziękuję Ci bardzo! – openfrog

+9

to działa, ale dla pojedynczego dotknięcia powoduje opóźnienie w wywołaniu pojedynczego dotknięcia – Mrug

+1

^^ Czy ktoś znalazł rozwiązanie tego opóźnienia? – barfoon

-1

Znalazłem rozwiązanie opóźnienia jednego dotknięcia przy użyciu odpowiedzi XCode Monkey. Korzystając z tego podejścia, możesz skonfigurować w mili-sekundach próg między jednym a podwójnym dotknięciem. Technika ta wykorzystuje prosty UIButton i NSTimer do rozróżnienia między jednym i dwoma dotknięciami.

@property NSTimer  *tapTimer; 
@property BOOL   isDoubleTap; 

    UIButton *yourButton = [UIButton new]; 
    yourButton.frame = // set your frame 
    [yourButton addTarget:self action:@selector(handleTap:) forControlEvents:UIControlEventTouchUpInside]; 
    [self.view yourButton]; 


-(void)handleTap:(UIButton*)button 
{ 
    [self.tapTimer invalidate]; 

    if (self.isDoubleTap) 
    { 
    [self doDoubleTap]; 
    return; 
    } 
    self.isDoubleTap = YES; 
    // CHANGE THE 0.3 SECOND THRESHOLD BETWEEN SINGLE/DOUBLE TAP TO YOUR HEART'S CONTENT 
    self.tapTimer = [NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(doSingleTap) userInfo:nil repeats:NO]; 
} 

-(void)doSingleTap 
{ 
    self.isDoubleTap = NO; 
} 

-(void)doDoubleTap 
{ 
    self.isDoubleTap = NO; 
} 
+0

Brak poprawy opóźnienia ORAZ stwarza potencjalne problemy z klikaniem przez użytkowników wielu komórek w czasie krótszym niż 0,3 sekundy. – ChuckKelly

+0

Musisz albo zachować znaczące (0,2) opóźnienie, albo wykrycie podwójnego dotknięcia nie uda się zarejestrować przed wygaśnięciem pojedynczego czasu. – Jeet

5

sprawie SWIFT 3 i szybkiego 4:

let singleTap = UITapGestureRecognizer(target: self, action: #selector(doSingleTap)) 
singleTap.numberOfTapsRequired = 1 

self.view.addGestureRecognizer(singleTap) 

let doubleTap = UITapGestureRecognizer(target: self, action: #selector(doDoubleTap)) 
doubleTap.numberOfTapsRequired = 2 

self.view.addGestureRecognizer(doubleTap) 

singleTap.require(toFail: doubleTap) 
+0

Używam singleTap.requireGestureRecognizerToFail (doubleTap) zamiast singleTap.require (toFail: doubleTap) – Marcos

+0

Odpowiedź jest dla Swift 3 @Marcos – Logan

0
{ 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]; 
     [self.headerView addGestureRecognizer:singleTap]; 
    } 
     - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{ 
      return YES; 
     } 

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

Utwórz rozpoznawania, czyli recognizers gest wewnątrz dowolnej metody chcesz. Na przykład, jeśli chcesz dotknąć gesty dla Twojego headerView w Tableview tworzyć te gesty kranu wewnątrz

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 

I klasa powinna realizować UIGestureRecognizerDelegate. Wyżej wymienione są 2 metody tej klasy delegatów.

+0

Niektóre wyjaśnienia znacznie poprawią jakość Twojej odpowiedzi. – mrun

Powiązane problemy