Kann ein UIButton (oder ein anderes Steuerelement) Berührungsereignisse empfangen, wenn der Rahmen des UIButton außerhalb des Rahmens des übergeordneten Elements liegt? Wenn ich dies versuche, scheint mein UIButton keine Ereignisse empfangen zu können. Wie kann ich das umgehen?
91
Antworten:
Ja. Sie können die
hitTest:withEvent:
Methode überschreiben , um eine Ansicht für einen größeren Satz von Punkten zurückzugeben, als diese Ansicht enthält. Siehe die UIView-Klassenreferenz .Bearbeiten: Beispiel:
Bearbeiten 2: (Nach Klarstellung :) Um sicherzustellen, dass die Schaltfläche innerhalb der Grenzen des übergeordneten Elements behandelt wird, müssen Sie das übergeordnete Element überschreiben
pointInside:withEvent:
, um den Rahmen der Schaltfläche einzuschließen.Beachten Sie, dass der Code nur zum Überschreiben von pointInside nicht ganz korrekt ist. Gehen Sie wie folgt vor, wie Summon unten erklärt:
Beachten Sie, dass Sie dies höchstwahrscheinlich
self.oversizeButton
als IBOutlet in dieser UIView-Unterklasse tun würden. Dann können Sie einfach die betreffende Schaltfläche "Übergröße" in die betreffende Sonderansicht ziehen. (Wenn Sie dies aus irgendeinem Grund häufig in einem Projekt tun, haben Sie eine spezielle UIButton-Unterklasse, und Sie können Ihre Unteransichtsliste nach diesen Klassen durchsuchen.) Ich hoffe, es hilft.quelle
pointInside:withEvent:
, um den Rahmen der Schaltfläche einzuschließen. Ich werde meiner obigen Antwort einen Beispielcode hinzufügen.hitTest:withEvent:
undpointInside:withEvent:
Bereich, der nicht für mich aufgerufen wird, wenn ich auf einen Knopf drücke, der außerhalb der Grenzen der Eltern liegt. Was kann falsch sein?@jnic, ich arbeite an iOS SDK 5.0 und damit Ihr Code richtig funktioniert, musste ich Folgendes tun:
Die Containeransicht ist in meinem Fall ein UIButton, und alle untergeordneten Elemente sind auch UIButtons, die sich außerhalb der Grenzen des übergeordneten UIButton bewegen können.
Beste
quelle
In der übergeordneten Ansicht können Sie die Treffer-Testmethode überschreiben:
In diesem Fall leiten Sie den Anruf dort weiter, wenn der Punkt innerhalb der Grenzen Ihrer Schaltfläche liegt. Wenn nicht, kehren Sie zur ursprünglichen Implementierung zurück.
quelle
In meinem Fall hatte ich eine
UICollectionViewCell
Unterklasse, die a enthieltUIButton
. Ich habeclipsToBounds
die Zelle deaktiviert und die Schaltfläche war außerhalb der Zellengrenzen sichtbar. Die Schaltfläche empfing jedoch keine Berührungsereignisse. Ich konnte die Berührungsereignisse auf der Schaltfläche mithilfe von Jacks Antwort erkennen: https://stackoverflow.com/a/30431157/3344977Hier ist eine Swift-Version:
Swift 4:
quelle
Warum passiert das?
Dies liegt daran, dass Berührungsereignisse, die tatsächlich in dieser Unteransicht auftreten, nicht an diese Unteransicht gesendet werden, wenn Ihre Unteransicht außerhalb der Grenzen Ihrer Übersicht liegt. Es ist jedoch WILL seine Superview geliefert werden.
Was musst du machen?
Wenn Ihre Übersicht das oben erwähnte Berührungsereignis empfängt, müssen Sie UIKit ausdrücklich mitteilen, dass meine Unteransicht diejenige sein sollte, die dieses Berührungsereignis empfängt.
Was ist mit dem Code?
Implementieren Sie in Ihrer Übersicht
func hitTest(_ point: CGPoint, with event: UIEvent?)
Faszinierende Gotchya: Sie müssen zur "höchsten zu kleinen Übersicht" gehen
Sie müssen "nach oben" zur "höchsten" Ansicht gehen, in der sich die Problemansicht befindet.
Typisches Beispiel:
Angenommen, Sie haben einen Bildschirm S mit einer Containeransicht C. Die Ansicht des Container Viewcontrollers ist V. (Rückruf V befindet sich innerhalb von C und hat die gleiche Größe.) V hat eine Unteransicht (möglicherweise eine Schaltfläche) B. B ist das Problem Ansicht, die tatsächlich außerhalb von V liegt.
Beachten Sie jedoch, dass B auch außerhalb von C liegt.
In diesem Beispiel haben Sie die Lösung anzuwenden
override hitTest
und zwar bis C, nicht zu V . Wenn Sie es auf V anwenden, tut es nichts.quelle
Schnell:
Wobei targetView die Ansicht ist, für die Sie das Ereignis empfangen möchten (die sich ganz oder teilweise außerhalb des Rahmens der übergeordneten Ansicht befinden kann).
quelle
Für mich (wie für andere) bestand die Antwort nicht darin , die
hitTest
Methode zu überschreiben , sondern diepointInside
Methode. Ich musste das nur an zwei Stellen tun.Die Übersicht Dies ist die Ansicht, dass
clipsToBounds
das gesamte Problem verschwinden würde , wenn es auf true gesetzt wäre. Also hier ist meine einfacheUIView
in Swift 3:Die Unteransicht Ihr Kilometerstand kann variieren, aber in meinem Fall musste ich auch die
pointInside
Methode für die Unteransicht überschreiben , bei der entschieden wurde, dass die Berührung außerhalb der Grenzen liegt. Meins ist in Ziel-C, also:Diese Antwort (und einige andere auf dieselbe Frage) kann Ihnen helfen, Ihr Verständnis zu verbessern.
quelle
Swift 4.1 aktualisiert
Um Berührungsereignisse in derselben UIView zu erhalten, müssen Sie nur die folgende Überschreibungsmethode hinzufügen. Dadurch wird eine bestimmte Ansicht identifiziert, die in UIView getippt wurde und außerhalb der Grenzen liegt
quelle