web-dev-qa-db-fra.com

Reconnaissance des gestes et actions des boutons

J'ai une hiérarchie de vues qui ressemble à ceci:

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

J'ai attaché un ou plusieurs identificateurs de geste à mon UIView (B). Le problème auquel je suis confronté est que je ne reçois aucune action pour le bouton Rectangle arrondi qui se trouve à l'intérieur de UIView (B). La reconnaissance des gestes singleTap capture/annule l'événement Touch Up Inside du bouton.

Comment puis-je le faire fonctionner? Je pensais que la hiérarchie de la chaîne de répondeurs ferait en sorte que l’événement tactile ait la préférence, et il SERA déclenché! Qu'est-ce que je rate?

Voici un code connexe:

#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;
    }
}
96
Mustafa

Dans la méthode "shouldReceiveTouch", vous devez ajouter une condition qui renverra NO si le contact est sur le bouton.

Ceci est tiré de l'exemple 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;
}

j'espère que ça va aider

Modifier

Comme Daniel l'a noté, vous devez vous conformer à UIGestureRecognizerDelegate pour que cela fonctionne.

shani

172
shannoga

J'ai aussi eu le même problème, alors j'ai essayé avec

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

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

Cela fonctionne maintenant parfaitement .........

50
Ramesh Chandran A

De manière générale, nous utilisons la méthode déléguée ci-dessous pour éviter le contact dans tous les types de contrôles UIC:

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

Remarque: NE faites PAS cette vérification (vérifiez le type de classe reconnaissizer.view) le gestureRecognizerShouldBegin, cela ne fonctionnera pas.

20
flypig

Voici une version Swift 3.:

extension UIViewController: UIGestureRecognizerDelegate {

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

N'oubliez pas de:

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

10
Marcelo Gracietti

Voici une version Swift:

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

N'oubliez pas de:

  1. Rendre votre classe conforme à UIGestureRecognizerDelegate
  2. Faites en sorte que votre objet tappeur se délègue à lui-même (par exemple: tapper.delegate = self)
6
rsc

La meilleure solution est, à mon sens, d'utiliser l'extrait de code ci-dessous:

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