2013-04-04 8 views
48

Ho bisogno di implementare una funzione che invocherà del codice quando toccherò due volte sul self.view (vista di UIViewCotroller). Ma il problema è che ho un altro oggetto UI su questa vista e non voglio collegare alcun oggetto riconoscitore a tutti loro. Ho trovato questo metodo sotto come fare un gesto sulla mia vista e so come funziona. In questo momento sono davanti all'handicap quale modo di scegliere per creare questo riconoscitore che ignora la sottoview. Qualche idea? Grazie.UITapGestureRecognizer tocca su self.view ma ignora le sottoview

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)]; 
[doubleTap setNumberOfTapsRequired:2]; 
[self.view addGestureRecognizer:doubleTap]; 
+0

Non sono sicuro, ma hai provato a fissare cancelsTouchesInView su NO sul riconoscitore? quindi [doubleTap setCancelsTouchesInView: NO]; – JDx

risposta

85

Si dovrebbe adottare il protocollo UIGestureRecognizerDelegate all'interno dell'oggetto self e chiamare il metodo seguito per controllare la vista. All'interno di questo metodo, controlla la tua vista contro touch.view e restituisci il bool appropriato (Sì/No). Qualcosa del genere:

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

Modifica: Per favore, controlla anche la risposta di @ Ian!

+0

un'altra domanda Ho pochi pulsanti sulla mia vista che devono funzionare. come posso impostare una priorità per loro? –

+0

se i pulsanti hanno i propri riconoscitori di gesti (probabile), scavare nel loro interno e prenderli e leggere i documenti su '- [UIGestureRecognizer requireGestureRecognizerToFail:]' ma potrebbe funzionare senza modificarli – bshirley

+0

cercava questo per ore ! Grazie! ;) – MasterRazer

10

E per la variante Swift:

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

Buono a sapere, isDescendantOfView restituisce un valore Boolean indica se il ricevitore è una visualizzazione secondaria di una determinata vista o identica a quella vista.

+1

Non dimenticare di impostare UIGestureRecognizerDelegate nella tua classe! – Fox5150

+1

Invece di farlo se affermazione, non puoi semplicemente restituirlo? return! Touch.isDescendant (of: gestureRecognizer.view) Inoltre, nuova sintassi in swift 3 ^^ – EdwardSanchez

33

Un altro approccio è quello di confrontare solo se la vista del tocco è la visualizzazione dei gesti, perché i discendenti non passeranno la condizione. Una bella, semplice one-liner:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { 
    return touch.view == gestureRecognizer.view 
} 
+1

Questo funziona meglio per me rispetto alla risposta accettata. Molto più conciso. –

+1

@In questo metodo non viene richiamato quando si tocca la vista. – Prabu

+0

Ottima risposta concisa! – scurioni

5

completa soluzione rapida (delegato deve essere implementato e set per riconoscitore (s)):

class MyViewController: UIViewController UIGestureRecognizerDelegate { 

    override func viewDidLoad() { 
     let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(onBaseTapOnly)) 
     doubleTapRecognizer.numberOfTapsRequired = 2 
     doubleTapRecognizer.delegate = self 
     self.view.addGestureRecognizer(doubleTapRecognizer) 
    } 

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

    func onBaseTapOnly(sender: UITapGestureRecognizer) { 
     if sender.state == .Ended { 
      //react to tap 
     } 
    } 
} 
1

Si noti che il gestureRecognizer API è cambiato a:

gestureRecognizer (_: shouldReceive :)

Prendere nota in particolare dell'indicatore di sottolineatura (salta) per l'etichetta esterna del primo parametro.

Utilizzando molti degli esempi sopra riportati, non ho ricevuto l'evento. Di seguito è riportato un esempio che funziona per le versioni correnti di Swift (3+).

0

Oltre alle soluzioni di cui sopra, non dimenticare di controllare User Interaction Enabled della sottoview.

enter image description here