Während die meisten Apple-Dokumente sehr gut geschrieben sind, halte ich ' Event Handling Guide für iOS ' für eine Ausnahme. Es fällt mir schwer, klar zu verstehen, was dort beschrieben wurde.
Das Dokument sagt:
Beim Testen von Treffern ruft ein Fenster
hitTest:withEvent:
die oberste Ansicht der Ansichtshierarchie auf. Bei dieser Methode wirdpointInside:withEvent:
jede Ansicht in der Ansichtshierarchie, die YES zurückgibt, rekursiv aufgerufen und die Hierarchie nach unten verschoben, bis die Unteransicht gefunden wird, innerhalb deren Grenzen die Berührung stattgefunden hat. Diese Ansicht wird zur Hit-Test-Ansicht.
Ist es also so, dass nur hitTest:withEvent:
die oberste Ansicht vom System aufgerufen wird, das pointInside:withEvent:
alle Unteransichten aufruft, und wenn die Rückkehr von einer bestimmten Unteransicht JA lautet, dann Aufrufe pointInside:withEvent:
der Unterklassen dieser Unteransicht?
Antworten:
Es scheint eine ziemlich grundlegende Frage zu sein. Aber ich stimme Ihnen zu, dass das Dokument nicht so klar ist wie andere Dokumente. Hier ist meine Antwort.
Die Implementierung von
hitTest:withEvent:
in UIResponder führt Folgendes aus:pointInside:withEvent:
vonself
hitTest:withEvent:
zurückgegebennil
. Das Ende der Geschichte.hitTest:withEvent:
Nachrichten an die Unteransichten gesendet. Es beginnt in der Unteransicht der obersten Ebene und wird in anderen Ansichten fortgesetzt, bis eine Unteransicht ein Nichtobjekt zurückgibtnil
oder alle Unteransichten die Nachricht empfangen.nil
zum ersten Mal ein Nichtobjekt zurückgibt , gibt die erstehitTest:withEvent:
dieses Objekt zurück. Das Ende der Geschichte.nil
, wird die erstehitTest:withEvent:
zurückgegebenself
Dieser Vorgang wird rekursiv wiederholt, sodass normalerweise die Blattansicht der Ansichtshierarchie schließlich zurückgegeben wird.
Sie können jedoch überschreiben
hitTest:withEvent
, um etwas anderes zu tun. In vielen Fällen ist das ÜberschreibenpointInside:withEvent:
einfacher und bietet dennoch genügend Optionen, um die Ereignisbehandlung in Ihrer Anwendung zu optimieren.quelle
hitTest:withEvent:
Meinst du, dass alle Unteransichten irgendwann ausgeführt werden?hitTest:withEvent:
Ihre Ansichten (undpointInside
wenn Sie möchten), drucken Sie ein Protokoll und rufen Sie[super hitTest...
an, um herauszufinden, werhitTest:withEvent:
in welcher Reihenfolge aufgerufen wird.Ich denke, Sie verwechseln Unterklassen mit der Ansichtshierarchie. Was der Arzt sagt, ist wie folgt. Angenommen, Sie haben diese Ansichtshierarchie. Nach Hierarchie spreche ich nicht von Klassenhierarchie, sondern von Ansichten innerhalb der Ansichtshierarchie wie folgt:
Angenommen, Sie legen Ihren Finger hinein
D
. Folgendes wird passieren:hitTest:withEvent:
wird aufgerufenA
, die oberste Ansicht der Ansichtshierarchie.pointInside:withEvent:
wird in jeder Ansicht rekursiv aufgerufen.pointInside:withEvent:
wird aufgerufenA
und kehrt zurückYES
pointInside:withEvent:
wird aufgerufenB
und kehrt zurückNO
pointInside:withEvent:
wird aufgerufenC
und kehrt zurückYES
pointInside:withEvent:
wird aufgerufenD
und kehrt zurückYES
YES
wird auf die Hierarchie geschaut, um die Unteransicht zu sehen, in der die Berührung stattgefunden hat. In diesem Fall ausA
,C
undD
wird es seinD
.D
wird die Hit-Test-Ansicht seinquelle
hitTest:withEvent:
B, C und D ebenfalls aufgerufen werden. Was passiert, wenn D eine Unteransicht von C ist, nicht A? Ich glaube, ich war verwirrt ...A
zurückkehrenYES
als auch, wieC
undD
tut?Ich finde dieses Hit-Testing in iOS sehr hilfreich
Bearbeiten Sie Swift 4:
quelle
Vielen Dank für die Antworten. Sie haben mir geholfen, die Situation mit "Overlay" -Ansichten zu lösen.
Angenommen
X
- die Berührung des Benutzers.pointInside:withEvent:
beiB
RückgabeNO
, alsohitTest:withEvent:
RückgabeA
. Ich habe eine Kategorie geschriebenUIView
, um Probleme zu lösen, wenn Sie die oberste sichtbare Ansicht berühren müssen .userInteractionEnabled
Einstellung auf sendenNO
.self
,self
wird dies als potenzielles Ergebnis betrachtet.Beachten Sie, dass
[self.subviewsreverseObjectEnumerator]
die Ansichtshierarchie von oben nach unten eingehalten werden muss. Überprüfen SieclipsToBounds
, ob maskierte Unteransichten nicht getestet werden sollen.Verwendung:
hitTest:withEvent:
dies durchDer offizielle Apple-Leitfaden bietet auch einige gute Illustrationen.
Hoffe das hilft jemandem.
quelle
Es zeigt sich wie dieser Ausschnitt!
quelle
Das Snippet von @lion wirkt wie ein Zauber. Ich habe es auf Swift 2.1 portiert und als Erweiterung für UIView verwendet. Ich poste es hier, falls jemand es braucht.
Um es zu verwenden, überschreiben Sie einfach hitTest: point: withEvent in Ihrer Ansicht wie folgt:
quelle
Klassen Diagramm
Hit Testing
Finde einen
First Responder
First Responder
in diesem Fall ist die tiefsteUIView
point()
Methode, von der true zurückgegeben wurdeIntern
hitTest()
sieht aus wieTouch-Ereignis an senden
First Responder
Schauen wir uns ein Beispiel an
Antwortkette
Schauen Sie sich das Beispiel an
[Android onTouch]
quelle