Übergeben von UI-Ereignissen über Ansichten in iOS

Einführung

In diesem Artikel wird sehr kurz erläutert, wie Touch-Ereignisse auf der Benutzeroberfläche von einer UIWindow / UIView-Instanz an eine andere übergeben werden.

Sie fragen sich vielleicht, ob es sich lohnt, es zu wissen? Standardmäßig erhält in einer einfachen, häufig verwendeten Anwendung die oberste Ansicht, die von einem in UIKit implementierten grundlegenden Mechanismus namens „hit-test“ bestimmt wird, Berührungsereignisse. Das Testen von Treffern ist kein Algorithmus mehr, der unsere Ansichtshierarchie durchläuft und die tiefste Ansicht findet, die den Berührungspunkt enthält und das Ereignis empfangen sollte.

Wenn Ihre Anwendung jedoch eine viel kompliziertere Benutzeroberfläche hat, müssen Sie möglicherweise andere Methoden zur Behandlung von Berührungsereignissen kennen.

userInteractionEnabled

Diese Eigenschaft, eine der grundlegenden Eigenschaften von UIView, gibt an, dass eine Ansicht für die Interaktion aktiviert ist oder nicht. Beim Treffer-Testen erhält eine Ansicht keine Berührungsereignisse, wenn ihr Status entweder userInteractionEnabled == false, isHidden == true oder alpha <0.01 lautet. Wenn wir möchten, dass unsere Ansichten angezeigt werden, aber keine Ereignisse empfangen werden, setzen Sie userInteractionEnabled einfach auf false.

PassthroughView

Ein Problem von userInteractionEnabled ist, dass die Unteransichten kaskadiert werden. Wenn eine Ansicht für die Interaktion deaktiviert ist, sind auch alle Unteransichten deaktiviert. Manchmal müssen wir eine Ansicht anzeigen, die einige Unteransichten enthält, wir müssen diese Unteransichten berühren können, aber auch unsere Übersicht fungiert als Hintergrundansicht, keine Ereignisse empfangen. Hier ist eine Möglichkeit, dies zu tun:

Hier deklariere ich eine Unterklasse von UIView und überschreibe das Standardverhalten von hitTest. Dann kann ich diese Klasse immer dann verwenden, wenn eine Ansicht eine Passthrough-Ansicht sein soll. Unten ist ein Beispiel, auf das ich unter UISwitch tippen kann.

PassthroughWindow

UIWindow ist nur ein spezielles UIView mit erweiterten Funktionen. Es ist jedoch ein sehr wichtiger Bestandteil einer iOS-Anwendung. Es ist gut zu lernen, wie es verwendet wird.

Ein Objekt, das den Hintergrund für die Benutzeroberfläche Ihrer App bildet und wichtige Verhaltensweisen bei der Ereignisbehandlung bietet. (Apples Dokumentation).

In einfachen Worten ist ein Fenster ein Objekt, das UI-Elemente darauf enthält. Jede App muss mindestens 1 Fenster haben, das normalerweise programmgesteuert im Code oder durch Festlegen von Ist der ursprüngliche View-Controller im Storyboard initialisiert wird.

Es wird empfohlen, dass eine App nur 1 Fenster hat. In einigen Fällen benötigen wir jedoch mehr. Zum Beispiel, wenn Sie ein anderes Fenster benötigen, um Dinge auf einem externen Bildschirm anzuzeigen. Wenn Sie ReplayKit für die Übertragung unseres Bildschirms verwenden, erfasst die Bibliothek unser Hauptfenster. Wenn Sie Informationen anzeigen möchten, die nicht wie Stoppschaltfläche oder Erfassungsstatus erfasst werden sollen, müssen Sie diese in einem anderen Fenster anzeigen.

Dann brauchen wir möglicherweise eine Möglichkeit, Berührungsereignisse durch Fenster zu leiten. Glücklicherweise ist ein UIWindow nur ein UIView, so dass wir folgendes deklarieren können:

Im Moment können wir ein PassthroughWindow oder eine PassthroughView und einige Unteransichten dazu erstellen. Was aber, wenn die Benutzeroberfläche nicht mehr einfach ist: Wir müssen ein Fenster mit einem komplexen Navigations-Controller darauf anzeigen (nun, es ist tatsächlich in meinem Projekt passiert).

Nun, Ereignisse werden über PassthroughView übergeben, aber nicht an PassthroughWindow, da sie in mittleren Ansichten wie BubblesViewController, UIViewControllerWrapperView, ... angehalten werden. Wir haben PassthroughView implementiert, können diese Ansichtsklasse jedoch nicht in PassthroughView ändern, da dies sonst sehr schwierig und frustriert wäre. Hier ist ein Trick, um dieses Problem zu lösen:

Jedes Mal, wenn ich eine PassthroughView teste, delegiere ich das Ergebnis der Trefferprüfung an mein PassthroughWindow. Natürlich funktioniert diese spezielle Unterklasse nur in diesem Fall. Sie können die Logik in Ihren Fällen ändern.

Wohin soll es von hier aus gehen?

Es gibt eine sehr hilfreiche WWDC-Sitzung zum Umgang mit Berührungen, die Sie unbedingt ansehen sollten: https://developer.apple.com/videos/play/wwdc2014/235/

Abgesehen von den Treffertests empfehle ich Ihnen auch, etwas über die Responder-Kette zu lesen - eine interessante Möglichkeit, die Ereignis-Responder zu wechseln.