Existe-t-il une condition de priorité entre les méthodes gestuelles (geste panoramique et geste de balayage)?
Question
Je développe une application dans laquelle j'ai utilisé le mouvement de panoramique ainsi que le mouvement de balayage.Donc, chaque fois que je fais le geste de balayage, mais la méthode du geste de panoramique est toujours appelée et la méthode de geste de balayage n'est pas appelée.
Y a-t-il une priorité entre toutes les méthodes gestuelles?
La solution
Vous pouvez les appeler en parallèle en implémentant la méthode suivante du protocole UIGestureRecognizerDelegate
:
- (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UISwipeGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Autres conseils
Il existe une propriété sur la classe UIGestureRecognizer
appelée "cancelsTouchesInView" qui par défaut est YES
.Cela entraînera l'annulation de tous les gestes en attente.Le mouvement de panoramique est reconnu en premier car il n'a pas besoin d'avoir un événement de «retouche», il annule donc le geste de balayage.
Si vous souhaitez que les deux gestes soient reconnus, essayez d'ajouter:
[yourPanGestureInstance setCancelsTouchesInView:NO];
Donner la priorité au balayage
Vous pouvez donner la priorité à un UIGestureRecognizer
avec la méthode require(toFail:)
.
@IBOutlet var myPanGestureRecognizer: UIPanGestureRecognizer!
@IBOutlet var mySwipeGestureRecognizer: UISwipeGestureRecognizer!
myPanGesture.require(toFail: mySwipeGestureRecognizer)
Désormais, votre panoramique ne s’exécutera que si votre balayage échoue.
Utilisez pan pour tout
Si les outils de reconnaissance de gestes swipe et pan ne fonctionnent pas correctement avec cette configuration, vous pouvez faire passer toute votre logique dans le panoramique reconnaissance de gestes pour plus de contrôle.
let minHeight: CGFloat = 100
let maxHeight: CGFloat = 700
let swipeVelocity: CGFloat = 500
var previousTranslationY: CGFloat = 0
@IBOutlet weak var cardHeightConstraint: NSLayoutConstraint!
@IBAction func didPanOnCard(_ sender: Any) {
guard let panGesture = sender as? UIPanGestureRecognizer else { return }
let gestureEnded = bool(panGesture.state == UIGestureRecognizerState.ended)
let velocity = panGesture.velocity(in: self.view)
if gestureEnded && abs(velocity.y) > swipeVelocity {
handlePanOnCardAsSwipe(withVelocity: velocity.y)
} else {
handlePanOnCard(panGesture)
}
}
func handlePanOnCard(_ panGesture: UIPanGestureRecognizer) {
let translation = panGesture.translation(in: self.view)
let translationYDelta = translation.y - previousTranslationY
if abs(translationYDelta) < 1 { return } // ignore small changes
let newCardHeight = cardHeightConstraint.constant - translationYDelta
if newCardHeight > minHeight && newCardHeight < maxHeight {
cardHeightConstraint.constant = newCardHeight
previousTranslationY = translation.y
}
if panGesture.state == UIGestureRecognizerState.ended {
previousTranslationY = 0
}
}
func handlePanOnCardAsSwipe(withVelocity velocity: CGFloat) {
if velocity.y > 0 {
dismissCard() // implementation not shown
} else {
maximizeCard() // implementation not shown
}
}
Voici une démonstration du code ci-dessus en action.