2011-01-28 13 views
94

mi hanno una gerarchia vista che sembra qualcosa di simile:azioni Riconoscimento e pulsanti Gesture

UIView (A) 
UIView > UIImageView 
UIView > UIView (B) 
UIView > UIView (B) > Rounded Rect Button 
UIView > UIView (B) > UIImageView 
UIView > UIView (B) > UILabel 

Ho attaccato gesto riconoscitore (s) al mio UIView (B). Il problema che sto affrontando è che non ottengo alcuna azione per il pulsante Rect arrotondato che si trova all'interno di UIView (B). Il rilevatore di gesti singleTap acquisisce/sostituisce l'evento Ritocco interno del pulsante.

Come posso farlo funzionare? Ho pensato che la gerarchia della catena di risposta avrebbe assicurato che l'evento di tocco del pulsante avesse la precedenza, e si innescherebbe! Cosa mi manca?

Ecco po 'di codice relativo:

#pragma mark - 
#pragma mark View lifecycle (Gesture recognizer setup) 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // double tap gesture recognizer 
    UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)]; 
    dtapGestureRecognize.delegate = self; 
    dtapGestureRecognize.numberOfTapsRequired = 2; 
    [self.viewB addGestureRecognizer:dtapGestureRecognize]; 

    // single tap gesture recognizer 
    UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)]; 
    tapGestureRecognize.delegate = self; 
    tapGestureRecognize.numberOfTapsRequired = 1; 
    [tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize]; 
    [self.viewB addGestureRecognizer:tapGestureRecognize]; 

    // add gesture recodgnizer to the grid view to start the edit mode 
    UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)]; 
    pahGestureRecognizer.delegate = self; 
    pahGestureRecognizer.minimumPressDuration = 0.5; 
    [self.viewB addGestureRecognizer:pahGestureRecognizer]; 

    [dtapGestureRecognize release]; 
    [tapGestureRecognize release]; 
    [pahGestureRecognizer release]; 
} 

#pragma mark - 
#pragma mark Button actions 

- (IBAction)buttonTouchUpInside:(id)sender { 
    NSLog(@"%s, %@", __FUNCTION__, sender); 
} 

#pragma mark - 
#pragma mark Gesture recognizer actions 


- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { 
    NSLog(@"%s", __FUNCTION__); 
} 

- (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { 
    NSLog(@"%s", __FUNCTION__); 
} 

- (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer { 

    switch (gestureRecognizer.state) { 

     case UIGestureRecognizerStateEnded: { 
      NSLog(@"%s", __FUNCTION__); 

      break; 
     } 
     default: 
      break; 
    } 
} 
+0

Il modo più semplice è quello di impostare cancelsTouchesInView = false –

risposta

165

Nel metodo "shouldReceiveTouch" si dovrebbe aggiungere una condizione che restituirà NO se il tocco è nel pulsante.

Questo è da esempio apple SimpleGestureRecognizers.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { 

    // Disallow recognition of tap gestures in the segmented control. 
    if ((touch.view == yourButton)) {//change it to your condition 
     return NO; 
    } 
    return YES; 
} 

auguriamo che contribuiscano

Modifica

Come Daniel notato è necessario conformarsi alle UIGestureRecognizerDelegate per farlo funzionare.

shani

+1

Ah !!! Sì, ho dimenticato questo -gestureRecognizer: shouldReceiveTouch: metodo. Grazie per avermi indicato nella giusta direzione. Anche se questo risolve il mio problema, ma non so ancora perché la gerarchia del responder non funzioni in questo caso. Probabilmente dovrebbe, ma non viene gestito da Apple. – Mustafa

+2

Il comportamento di UIGestureRecognizer è chiaramente descritto come separato dalla catena di risposta "normale". Questa è una decisione progettuale di Apple. –

+9

Ricordarsi di conformarsi al protocollo UIGestureRecognizerDelegate e impostare il delegato di UIGestureRecognizer su quell'oggetto. – Daniel

48

Ho anche avuto lo stesso problema, poi ho provato con

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{ 

    if ([touch.view isKindOfClass:[UIButton class]]) {  //change it to your condition 
     return NO; 
    } 
    return YES; 
} 

Si sta lavorando ormai perfettamente .........

+2

mi manca solo il 'myGestureRecognizer.delegate = self;' – zero3nna

18

In generale, usiamo di seguito metodo delegato per evitare il contatto in tutti i tipi di UIControls:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { 
    if (([touch.view isKindOfClass:[UIControl class]])) { 
     return NO; 
    } 
    return YES; 
} 

Nota: Non fare questo controllo (C diamine il tipo di classe recognizer.view) the gestureRecognizerShouldBegin, non funzionerà.

4

La soluzione migliore è quella di utilizzare la mia mente frammento di codice di seguito:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { 
    CGPoint touchLocation = [touch locationInView:self.view]; 
    return !CGRectContainsPoint(self.menuButton.frame, touchLocation); 
} 
6

Ecco una versione Swift:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { 
    if (touch.view!.isKindOfClass(UIButton)) { 
     return false 
    } 
    return true 
} 

Non dimenticare di:

  1. fate classe conforme a UIGestureRecognizerDelegate
  2. Crea il tuo oggetto tapper de legato a sé (ad esempio tapper.delegate = self)
6

Ecco uno Swift 3.0 versione:

extension UIViewController: UIGestureRecognizerDelegate { 

public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { 
    if touch.view is UIButton { 
     return false 
    } 
    return true 
} 

Non dimenticare di:

Make your tapper object delegate to self (e.g: tapper.delegate = self)

Problemi correlati