Hareket tanıyıcı ve düğme eylemleri


99

Şuna benzeyen bir görünüm hiyerarşim var:

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

UIView'uma (B) hareket tanıyıcı (lar) ekledim. Karşılaştığım sorun, UIView (B) içindeki Rounded Rect Button için herhangi bir eylem almadığım. SingleTap hareket tanıyıcı, düğmenin İçe Rötuş olayını yakalar / geçersiz kılar.

Nasıl çalıştırabilirim? Yanıt veren zincir hiyerarşisinin, düğmeye dokunma olayının tercih edilmesini sağlayacağını ve tetikleneceğini düşündüm! Neyi kaçırıyorum?

İşte bazı ilgili kodlar:

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

En basit yol, cancelsTouchesInView = false
Bagusflyer

Yanıtlar:


176

"ShouldReceiveTouch" yönteminde, dokunma düğmenin içindeyse HAYIR döndürecek bir koşul eklemelisiniz.

Bu apple SimpleGestureRecognizers örneğinden alınmıştır.

- (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;
}

umarım yardımcı olur

Düzenle

Daniel'in belirttiği UIGestureRecognizerDelegategibi, işe yaraması için buna uymalısınız .

shani


1
Ah!!! Evet, -gestureRecognizer: shouldReceiveTouch: method'u unuttum. Beni doğru yönü gösterdiğin için teşekkürler. Bu sorunumu çözse de, bu durumda yanıt veren hiyerarşisinin neden çalışmadığını hala bilmiyorum. Muhtemelen olmalı, ancak Apple tarafından ele alınmıyor.
Mustafa

2
UIGestureRecognizer davranışı, "normal" yanıtlayıcı zincirinden ayrı olarak açıkça tanımlanmıştır. Bu, Apple tarafından verilen bir tasarım kararıdır.
Sylvain G.

11
UIGestureRecognizerDelegate Protokolüne uymayı ve UIGestureRecognizer'ın temsilcisini bu nesneye ayarlamayı unutmayın.
Daniel

2
Daha geniş kullanım için, Ramesh'in veya flypig'in test maddelerindeki bazı varyantları düşünün. Benim durumumda, örneğin, şu satırı elde ettim: if ( [touch.view isKindOfClass:[UIControl class]] || [[touch.view superview] isKindOfClass:[UITableViewCell class]] ) {... Özel bir sınıfın üyesi olan contentView'lerinde tableview hücrelerine "dokunduğunu" not edin, bu yüzden orada süpervizörün sınıfını kontrol ediyoruz.
clozach

Cevap için teşekkür ederim! Benim durumumda, aynı problemle karşılaştım ama sadece gerçek cihazda test edene kadar keşfettim. Bu yanıtta belirtildiği gibi UIGestureDelegate'i kullanmadan uygulamayı simülatörde çalıştırmak yanlış olsa da beklendiği gibi çalıştı.
Luis Artola

51

Ben de aynı sorunu yaşadım, sonra denedim

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

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

Şimdi mükemmel çalışıyor .........


4
sadecemyGestureRecognizer.delegate = self;
zero3nna

20

Genel olarak konuşursak, her tür UIControls'de dokunmayı önlemek için aşağıdaki delege yöntemini kullanırız:

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

Not: Bu denetimi YAPMAYIN (tanıyıcı.view sınıf türünü kontrol edin) hareketRecognizerShouldBegin, çalışmaz.


11

İşte bir Swift 3.0 sürümü:

extension UIViewController: UIGestureRecognizerDelegate {

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

Unutmayın:

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


6

İşte bir Swift versiyonu:

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

Unutmayın:

  1. Sınıfına uymanı sağla UIGestureRecognizerDelegate
  2. (Örn: Kendine sizin uzantılar nesne temsilci olun tapper.delegate = self)

5

En iyi çözüm, aşağıdaki kod parçacığını kullanmaktır:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint touchLocation = [touch locationInView:self.view];
    return !CGRectContainsPoint(self.menuButton.frame, touchLocation);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.