Frage UIGestureRecognizer blockiert Unteransicht für die Behandlung von Berührungsereignissen


Ich versuche herauszufinden, wie das gemacht wird der richtige Weg. Ich habe versucht, die Situation darzustellen: enter image description here

Ich füge ein UITableView als Unteransicht von a UIView. Das UIView reagiert auf einen Tap- und pinchGestureRecognizer, aber wenn dies geschieht, reagiert die Tabellenansicht nicht mehr auf diese beiden Gesten (es reagiert immer noch auf Swipes).

Ich habe es mit dem folgenden Code gemacht, aber es ist offensichtlich keine nette Lösung und ich bin mir sicher, dass es einen besseren Weg gibt. Dies ist in der UIView (die 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


Ursprung


Antworten:


Ich hatte ein sehr ähnliches Problem und fand meine Lösung in dieser SO Frage. Zusammenfassend stellen Sie sich als Delegierter für Ihre UIGestureRecognizer und überprüfen Sie dann die Zielansicht, bevor Ihr Erkenner die Berührung verarbeitet. Die relevante Delegate-Methode ist:

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

177
2018-05-04 17:35



Das Blockieren von Berührungsereignissen auf Unteransichten ist das Standardverhalten. Sie können dieses Verhalten ändern:

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

96
2017-07-20 06:05



Eine Möglichkeit besteht darin, Ihren Gestenerkenner (falls noch nicht vorhanden) zu unterklassifizieren und zu überschreiben -touchesBegan:withEvent: so dass bestimmt wird, ob jede Berührung in einer ausgeschlossenen Unteransicht und in Aufrufen begonnen hat -ignoreTouch:forEvent: für diese Berührung, wenn es tat.

Natürlich müssen Sie auch eine Eigenschaft hinzufügen, um die ausgeschlossene Unteransicht oder, besser, ein Array von ausgeschlossenen Unteransichten zu verfolgen.


4
2018-03-08 15:49



Ich habe eine Dropdown-Unteransicht mit einer eigenen Tabellenansicht angezeigt. Als Ergebnis der touch.view würde manchmal Klassen wie zurückkehren UITableViewCell. Ich musste durch die Oberklasse (n) gehen, um sicherzustellen, dass es die Unterklasse war, die ich dachte:

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



Es ist möglich ohne eine Klasse zu erben.

Sie können GestenRecognizers in der Callback-Auswahl der Gesten überprüfen

Wenn view.gestureRecognizers nicht Ihren GestenRecognizer enthält, ignorieren Sie ihn einfach

beispielsweise

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

Überprüfen Sie view.gestureRecognizers hier

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



Ich habe eine UIGestureRecognizer-Unterklasse erstellt, die alle Gestenerkenner blockiert, die an Übersichten einer bestimmten Ansicht angehängt sind.

Es ist Teil meines WEPopover-Projekts. Du kannst es finden Hier.


1
2017-09-18 14:56



Aufbauend auf @Pin Shih Wang Antworten. Wir ignorieren alle Abzweigungen, die nicht in der Ansicht enthalten sind, die die Erkennung der Tippgeste enthält. Alle Taps werden wie gewohnt an die View-Hierarchie weitergeleitet tapGestureRecognizer.cancelsTouchesInView = false. Hier ist der Code in 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



Ich machte auch ein Popover und so habe ich es gemacht

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



Sie können es aus- und einschalten .... in meinem Code habe ich so etwas gemacht, wie ich es ausschalten musste, wenn die Tastatur nicht angezeigt wurde, Sie können es auf Ihre Situation anwenden:

Rufen Sie dies ist viewdidload etc:

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

dann erstellen Sie die zwei Methoden:

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

Was dies bewirkt, deaktiviert den Wasserhahn. Ich musste den Tipp in eine Instanzvariable umwandeln und sie in dealloc freigeben.


0
2017-12-01 04:12



Implementieren Sie einen Delegaten für alle Erkenner von parentView und fügen Sie die Methode "gesticRecognizer" in den Delegaten ein, der für das gleichzeitige Triggern von Recognizern verantwortlich ist:

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

}

U kann die fail-Methoden verwenden, wenn Sie möchten, dass die untergeordneten Elemente ausgelöst werden, nicht jedoch die übergeordneten Erkennungen:

https://developer.apple.com/reference/uikit/uigestureco nzeredelegate


0
2017-12-12 11:01