Pertanyaan UIGestureRecognizer memblokir subview untuk menangani acara sentuh


Saya mencoba mencari tahu bagaimana ini dilakukan jalan yang benar. Saya sudah mencoba menggambarkan situasinya: enter image description here

Saya menambahkan a UITableView sebagai subview a UIView. Itu UIView merespons tap-dan pinchGestureRecognizer, tetapi ketika melakukannya, tampilan tabel berhenti bereaksi terhadap dua gerakan tersebut (masih bereaksi terhadap gesekan).

Saya telah membuatnya bekerja dengan kode berikut, tetapi ini jelas bukan solusi yang bagus dan saya yakin ada cara yang lebih baik. Ini dimasukkan ke dalam UIView (superview):

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if([super hitTest:point withEvent:event] == self) {
        for (id gesture in self.gestureRecognizers) {
            [gesture setEnabled:YES];
        }
        return self;
    }
    for (id gesture in self.gestureRecognizers) {
        [gesture setEnabled:NO];
    }
    return [self.subviews lastObject];
}

74
2018-03-07 17:32


asal


Jawaban:


Saya memiliki masalah yang sangat mirip dan menemukan solusi saya dalam pertanyaan SO ini. Singkatnya, tentukan diri Anda sebagai delegasi untuk Anda UIGestureRecognizer dan kemudian periksa tampilan yang ditargetkan sebelum mengizinkan pengenal Anda memproses sentuhan. Metode delegasi yang relevan adalah:

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

177
2018-05-04 17:35



Pemblokiran acara sentuh ke sublihat adalah perilaku default. Anda dapat mengubah perilaku ini:

UITapGestureRecognizer *r = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(agentPickerTapped:)];
r.cancelsTouchesInView = NO;
[agentPicker addGestureRecognizer:r];

96
2017-07-20 06:05



Salah satu kemungkinan adalah subclass recognure gesture Anda (jika Anda belum melakukannya) dan menimpa -touchesBegan:withEvent: sehingga menentukan apakah setiap sentuhan dimulai di sub-sesi dan panggilan yang dikecualikan -ignoreTouch:forEvent: untuk sentuhan itu jika itu terjadi.

Tentunya, Anda juga perlu menambahkan properti untuk melacak subklusi yang dikecualikan, atau mungkin lebih baik, larik sub-proyek yang dikecualikan.


4
2018-03-08 15:49



Saya menampilkan sub-tabir dropdown yang memiliki tampilan tabel sendiri. Akibatnya, itu touch.view kadang-kadang akan mengembalikan kelas seperti UITableViewCell. Saya harus melangkah melalui superclass (es) untuk memastikan itu adalah subclass yang saya pikir itu:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    UIView *view = touch.view;
    while (view.class != UIView.class) {
        // Check if superclass is of type dropdown
        if (view.class == dropDown.class) { // dropDown is an ivar; replace with your own
            NSLog(@"Is of type dropdown; returning NO");
            return NO;
        } else {
            view = view.superview;
        }
    }

    return YES;
}

4
2017-07-24 11:43



Adalah mungkin untuk melakukannya tanpa mewarisi kelas apa pun.

Anda dapat memeriksa gestureRecognizers di pemilih panggilan balik gesture

jika view.gestureRecognizers tidak berisi gestureRecognizer Anda, abaikan saja

sebagai contoh

- (void)viewDidLoad
{
    UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self     action:@selector(handleSingleTap:)];
    singleTapGesture.numberOfTapsRequired = 1;
}

periksa view.gestureRecognizers di sini

- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer
{
    UIEvent *event = [[UIEvent alloc] init];
    CGPoint location = [gestureRecognizer locationInView:self.view];

    //check actually view you hit via hitTest
    UIView *view = [self.view hitTest:location withEvent:event];

    if ([view.gestureRecognizers containsObject:gestureRecognizer]) {
        //your UIView
        //do something
    }
    else {
        //your UITableView or some thing else...
        //ignore
    }
}

2
2018-04-14 05:09



Saya membuat subclass UIGestureRecognizer yang dirancang untuk memblokir semua recognizers gerakan yang dilampirkan ke superviews dari tampilan tertentu.

Ini adalah bagian dari proyek WEPopover saya. Kamu bisa menemukannya sini.


1
2017-09-18 14:56



Membangun @Pin Shih Wang menjawab. Kami mengabaikan semua ketukan selain yang ada di tampilan yang berisi recognizer tap touchure. Semua ketukan diteruskan ke hierarki tampilan seperti biasa seperti yang kami tetapkan tapGestureRecognizer.cancelsTouchesInView = false. Berikut adalah kode di Swift3 / 4:

func ensureBackgroundTapDismissesKeyboard() {
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
    tapGestureRecognizer.cancelsTouchesInView = false
    self.view.addGestureRecognizer(tapGestureRecognizer)
}

@objc func handleTap(recognizer: UIGestureRecognizer) {
    let location = recognizer.location(in: self.view)
    let hitTestView = self.view.hitTest(location, with: UIEvent())
    if hitTestView?.gestureRecognizers?.contains(recognizer) == .some(true) {
        // I dismiss the keyboard on a tap on the scroll view
        // REPLACE with own logic
        self.view.endEditing(true)
    }
}

1
2017-09-27 12:33



Saya juga melakukan popover dan ini adalah bagaimana saya melakukannya

func didTap(sender: UITapGestureRecognizer) {

    let tapLocation = sender.locationInView(tableView)

    if let _ = tableView.indexPathForRowAtPoint(tapLocation) {
        sender.cancelsTouchesInView = false
    }
    else {
        delegate?.menuDimissed()
    }
}

0
2017-10-29 20:06



Anda dapat mematikannya dan pada .... di kode saya saya melakukan sesuatu seperti ini karena saya perlu mematikannya ketika keyboard tidak muncul, Anda dapat menerapkannya ke situasi Anda:

sebut ini viewdidload dll:

NSNotificationCenter    *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(notifyShowKeyboard:) name:UIKeyboardDidShowNotification object:nil];
[center addObserver:self selector:@selector(notifyHideKeyboard:) name:UIKeyboardWillHideNotification object:nil];

kemudian buat dua metode:

-(void) notifyShowKeyboard:(NSNotification *)inNotification 
{
    tap.enabled=true;  // turn the gesture on
}

-(void) notifyHideKeyboard:(NSNotification *)inNotification 
{
    tap.enabled=false;  //turn the gesture off so it wont consume the touch event
}

Apa yang dilakukan adalah menonaktifkan keran. Saya harus mengubah tap menjadi variabel instan dan merilisnya di dealloc.


0
2017-12-01 04:12



terapkan delegasi untuk semua pengenal parentView dan letakkan metode gestureRecognizer di delegasi yang bertanggung jawab untuk memicu pengenal simultan:

func gestureRecognizer(UIGestureRecognizer,       shouldBeRequiredToFailByGestureRecognizer:UIGestureRecognizer) -> Bool {
if (otherGestureRecognizer.view.isDescendantOfView(gestureRecognizer.view)) {
    return true
    } else {
    return false
}

}

Anda dapat menggunakan metode gagal jika Anda ingin membuat anak-anak terpicu tetapi tidak orang tua yang mengenali:

https://developer.apple.com/reference/uikit/uigesturerecognizerdelegate


0
2017-12-12 11:01