Pengenal gerakan dan tindakan tombol

99

Saya memiliki hierarki tampilan yang terlihat seperti ini:

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

Saya telah melampirkan pengenal isyarat ke UIView (B) saya. Masalah yang saya hadapi adalah bahwa saya tidak mendapatkan tindakan apa pun untuk Tombol Persegi Bulat yang ada di dalam UIView (B). Pengenal gerakan SingleTap menangkap / menimpa acara Touch Up Inside tombol.

Bagaimana cara membuatnya bekerja? Saya berpikir bahwa hierarki rantai responden akan memastikan bahwa peristiwa sentuhan tombol akan diberi preferensi, dan AKAN dipicu! Apa yang saya lewatkan?

Berikut beberapa kode terkait:

#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;
    }
}
Mustafa
sumber
Cara termudah adalah dengan menyetel cancelsTouchesInView = false
Bagusflyer

Jawaban:

176

Dalam metode "shouldReceiveTouch", Anda harus menambahkan ketentuan yang akan mengembalikan NO jika tombol disentuh.

Ini dari contoh SimpleGestureRecognizers apel .

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

semoga membantu

Edit

Seperti yang dicatat Daniel, Anda harus menyesuaikan diri UIGestureRecognizerDelegateagar berfungsi.

shani

shannoga.dll
sumber
1
Ah!!! Ya, saya lupa tentang metode -gestureRecognizer: shouldReceiveTouch: ini. Terima kasih telah mengarahkan saya ke arah yang benar. Meskipun ini menyelesaikan masalah saya, tetapi saya masih tidak tahu mengapa hierarki responden tidak berfungsi dalam kasus ini. Mungkin seharusnya begitu, tetapi tidak ditangani oleh Apple.
Mustafa
2
Perilaku UIGestureRecognizer secara jelas dijelaskan sebagai terpisah dari rantai responden "normal". Ini adalah keputusan desain Apple.
Sylvain G.
11
Ingatlah untuk mematuhi Protokol UIGestureRecognizerDelegate dan setel delegasi UIGestureRecognizer ke objek itu.
Daniel
2
Untuk penggunaan yang lebih luas, pertimbangkan beberapa varian pada klausa uji Ramesh atau flypig. Dalam kasus saya, misalnya, saya berakhir dengan baris: if ( [touch.view isKindOfClass:[UIControl class]] || [[touch.view superview] isKindOfClass:[UITableViewCell class]] ) {... Perhatikan bahwa sel tampilan tabel "disentuh" ​​di contentView mereka, yang merupakan anggota kelas privat, jadi di sana kami memeriksa kelas superview sebagai gantinya.
clozach
Terima kasih atas jawabannya! Dalam kasus saya, saya mengalami masalah yang sama tetapi saya menemukannya hanya sampai saya mengujinya di perangkat yang sebenarnya. Menjalankan aplikasi di simulator tanpa menggunakan UIGestureDelegate seperti yang ditunjukkan dalam jawaban ini bekerja seperti yang diharapkan meskipun salah.
Luis Artola
51

Saya juga mengalami masalah yang sama, lalu saya coba

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

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

Ini bekerja dengan sempurna sekarang .........

Ramesh Chandran A
sumber
4
saya hanya melewatkanmyGestureRecognizer.delegate = self;
zero3nna
20

Secara umum, kami menggunakan metode delegasi di bawah ini untuk menghindari sentuhan di semua jenis UIControls:

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

Catatan: JANGAN lakukan pemeriksaan ini (periksa jenis kelas pengenal.view) gestureRecognizerShouldBegin, itu tidak akan berfungsi.

flypig
sumber
11

Ini adalah versi Swift 3.0 :

extension UIViewController: UIGestureRecognizerDelegate {

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

Jangan lupa untuk:

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

Marcelo Gracietti
sumber
6

Ini adalah versi Swift:

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

Jangan lupa untuk:

  1. Membuat Anda sesuai dengan kelas UIGestureRecognizerDelegate
  2. Membuat delegasi penyadap objek untuk diri (misalnya: tapper.delegate = self)
rsc
sumber
5

Solusi terbaik adalah menurut saya menggunakan cuplikan kode di bawah ini:

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