J'ai vue avec un UITapGestureRecognizer
. Ainsi, lorsque je tape sur la vue, une autre vue apparaît au-dessus de cette vue. Cette nouvelle vue comporte trois boutons. Lorsque j'appuie maintenant sur l'un de ces boutons, je n'obtiens pas l'action des boutons, je n'obtiens que l'action du geste du toucher. Je ne peux donc plus utiliser ces boutons. Que puis-je faire pour transmettre les événements à ces boutons? La chose étrange est que les boutons sont toujours mis en évidence.
Je ne peux pas simplement supprimer UITapGestureRecognizer après avoir reçu son robinet. Parce qu'avec lui, la nouvelle vue peut également être supprimée. Signifie que je veux un comportement comme les contrôles vidéo plein écran .
void
afin de ne laisser aucune information derrière lors de l'exécution à utiliser pour la détection. Mais ce que vous pouvez faire, c'est remonter la hiérarchie des vues, testerUIControl
et revenirNO
si vous trouvez des contrôles.Pour faire suite au suivi de Casey à la réponse de Kevin Ballard:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if ([touch.view isKindOfClass:[UIControl class]]) { // we touched a button, slider, or other UIControl return NO; // ignore the touch } return YES; // handle the touch }
Cela permet essentiellement à tous les types de commandes d'entrée utilisateur comme les boutons, les curseurs, etc.
la source
setCancelsTouchesInView = NO
de ne pas déclencher le geste de toucher lors de l'interaction avec les commandes. Cependant, vous pouvez mieux l'écrire:return ![touch.view isKindOfClass:[UIControl class]];
J'ai trouvé cette réponse ici: lien
Vous pouvez aussi utiliser
tapRecognizer.cancelsTouchesInView = NO;
Ce qui empêche le module de reconnaissance des taps d'être le seul à capturer tous les taps
UPDATE - Michael a mentionné le lien vers la documentation décrivant cette propriété: cancelsTouchesInView
la source
Pour faire suite à la réponse de Kevin Ballard, j'ai eu le même problème et j'ai fini par utiliser ce code:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if ([touch.view isKindOfClass:[UIButton class]]){ return NO; } return YES; }
Cela a le même effet mais cela fonctionnera sur n'importe quel UIButton à n'importe quelle profondeur de vue (mon UIButton avait plusieurs vues de profondeur et le délégué de UIGestureRecognizer n'y faisait pas référence.)
la source
Dans iOS 6.0 et versions ultérieures, les actions de contrôle par défaut empêchent le chevauchement du comportement de reconnaissance de gestes. Par exemple, l'action par défaut pour un bouton est une simple pression. Si vous disposez d'un outil de reconnaissance de gestes en un seul clic associé à la vue parent d'un bouton et que l'utilisateur appuie sur le bouton, la méthode d'action du bouton reçoit l'événement tactile au lieu de la reconnaissance de gestes. Cela s'applique uniquement à la reconnaissance des gestes qui chevauche l'action par défaut d'un contrôle, qui comprend: .....
De la documentation d'API d'Apple
la source
Ces réponses étaient incomplètes. J'ai dû lire plusieurs articles sur la façon d'utiliser cette opération booléenne.
Dans votre fichier * .h, ajoutez ceci
@interface v1ViewController : UIViewController <UIGestureRecognizerDelegate>
Dans votre fichier * .m, ajoutez ceci
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { NSLog(@"went here ..."); if ([touch.view isKindOfClass:[UIControl class]]) { // we touched a button, slider, or other UIControl return NO; // ignore the touch } return YES; // handle the touch } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //tap gestrure UITapGestureRecognizer *tapGestRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenTappedOnce)]; [tapGestRecog setNumberOfTapsRequired:1]; [self.view addGestureRecognizer:tapGestRecog]; // This line is very important. if You don't add it then your boolean operation will never get called tapGestRecog.delegate = self; } -(IBAction) screenTappedOnce { NSLog(@"screenTappedOnce ..."); }
la source
J'ai trouvé une autre façon de le faire à partir d' ici . Il détecte le toucher que ce soit à l'intérieur de chaque bouton ou non.
(1) pointInside: withEvent: (2) locationInView:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { // Don't recognize taps in the buttons return (![self.button1 pointInside:[touch locationInView:self.button1] withEvent:nil] && ![self.button2 pointInside:[touch locationInView:self.button2] withEvent:nil] && ![self.button3 pointInside:[touch locationInView:self.button3] withEvent:nil]); }
la source
Swift 5
Bouton sur superview avec tapgesture
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if let _ = touch.view as? UIButton { return false } return true }
Dans mon cas, la mise en œuvre de hitTest a fonctionné pour moi. J'avais une vue de collection avec un bouton
Cette méthode parcourt la hiérarchie des vues en appelant la
point(inside:with:)
méthode de chaque sous-vue pour déterminer quelle sous-vue doit recevoir un événement tactile. Sipoint(inside:with:)
renvoie true, la hiérarchie de la sous-vue est parcourue de la même manière jusqu'à ce que la vue la plus au premier plan contenant le point spécifié soit trouvée.override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { guard isUserInteractionEnabled else { return nil } guard !isHidden else { return nil } guard alpha >= 0.01 else { return nil } guard self.point(inside: point, with: event) else { return nil } for eachImageCell in collectionView.visibleCells { for eachImageButton in eachImageCell.subviews { if let crossButton = eachImageButton as? UIButton { if crossButton.point(inside: convert(point, to: crossButton), with: event) { return crossButton } } } } return super.hitTest(point, with: event) }
la source
Voici la version Swift de la réponse de Lily Ballard qui a fonctionné pour moi:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if (scrollView.superview != nil) { if ((touch.view?.isDescendantOfView(scrollView)) != nil) { return false } } return true }
la source
Vous pouvez empêcher UITapGestureRecognizer d'annuler d'autres événements (comme le fait d'appuyer sur votre bouton) en définissant la valeur booléenne suivante:
[tapRecognizer setCancelsTouchesInView:NO];
la source
Si votre scénario est comme ceci:
Vous avez une vue simple et quelques UIButtons, contrôles UITextField ajoutés en tant que sous-vues à cette vue. Vous voulez maintenant fermer le clavier lorsque vous touchez n'importe où ailleurs dans la vue, sauf sur les commandes (sous-vues que vous avez ajoutées)
Alors la solution est:
Ajoutez la méthode suivante à votre XYZViewController.m (qui a votre vue)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; }
la source
En optimisant la réponse de cdasher, vous obtenez
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { return ![touch.view isKindOfClass:[UIControl class]]; }
la source