In den folgenden Abschnitten werden einige wichtige Konzepte für das Drag-and-drop-Verfahren erläutert.
Drag-and-drop-Prozess
Beim Drag-and-drop-Verfahren gibt es vier Schritte oder Status: „Started“ (Gestartet), „Continuing“ (Fortgesetzt), „Dropped“ (Abgelegt) und „Ended“ (Beendet).
- Gestartet
Als Reaktion auf die Ziegesten eines Nutzers ruft Ihre Anwendung
startDragAndDrop()
auf, um das System zum Starten eines Drag-and-drop-Vorgangs aufzufordern. Die Argumente der Methode bieten folgende Möglichkeiten:- Die Daten, die Sie verschieben möchten.
- Ein Callback zum Zeichnen des Schattens beim Ziehen
- Metadaten, die die gezogenen Daten beschreiben
- Das System ruft daraufhin Ihre Anwendung zurück, um einen Schatten für das Ziehen abzurufen. Das System zeigt dann den Schatten des Ziehens auf dem Gerät an.
- Als Nächstes sendet das System ein Drag-Ereignis mit dem Aktionstyp
ACTION_DRAG_STARTED
an den Drag-Ereignis-Listener allerView
-Objekte im aktuellen Layout. Damit weiterhin Drag-Ereignisse empfangen werden, einschließlich eines möglichen Drop-Ereignisses, muss der Drag-Ereignis-Listenertrue
zurückgeben. Dadurch wird der Listener beim System registriert. Nur registrierte Listener erhalten weiterhin Drag-Ereignisse. An dieser Stelle können Listener auch das Erscheinungsbild ihres Drop-ZielobjektsView
ändern, um anzuzeigen, dass die Ansicht ein Drop-Ereignis akzeptieren kann. - Wenn der Drag-Ereignis-Listener
false
zurückgibt, werden erst dann Drag-Ereignisse für den aktuellen Vorgang empfangen, wenn das System ein Drag-Ereignis mit dem AktionstypACTION_DRAG_ENDED
sendet. Durch das Zurückgeben vonfalse
teilt der Listener dem System mit, dass er nicht am Drag-and-drop-Vorgang interessiert ist und die gezogenen Daten nicht akzeptieren möchte.
- Wird fortgesetzt
- Der Nutzer zieht das Element weiter. Wenn der Schatten des Objekts, das verschoben wird, den Begrenzungsrahmen eines Drop-Ziels schneidet, sendet das System ein oder mehrere Drag-Ereignisse an den Drag-Ereignis-Listener des Ziels. Der Listener kann das Aussehen des Drop-Ziels
View
als Reaktion auf das Ereignis ändern. Wenn das Ereignis beispielsweise angibt, dass der Schatten des Objekts, das gezogen wird, den Begrenzungsrahmen des Drop-Ziels betritt (AktiontypACTION_DRAG_ENTERED
), kann der Listener reagieren, indem er dasView
hervorhebt. - Abgebrochen
- Der Nutzer lässt den Schatten des Ziehvorgangs innerhalb des Begrenzungsrahmens eines Drop-Ziels los. Das System sendet dem Listener des Drop-Ziels ein Ziehereignis mit dem Aktionstyp
ACTION_DROP
. Das Drag-Ereignisobjekt enthält die Daten, die über den Aufruf vonstartDragAndDrop()
an das System übergeben werden, wodurch der Vorgang gestartet wird. Der Listener muss dem System den booleschen Werttrue
zurückgeben, wenn er die verworfenen Daten erfolgreich verarbeitet hat. : Dieser Schritt tritt nur auf, wenn der Nutzer den Schatten des Objekts innerhalb des Begrenzungs-Quaders einesView
ablegt, dessen Listener für das Empfangen von Drag-Ereignissen registriert ist (Drop-Ziel). Wenn der Nutzer den Schatten in einer anderen Situation loslässt, wird keinACTION_DROP
-Drag-Ereignis gesendet. - Beendet
Nachdem der Nutzer den Schatten losgelassen und das System
ein Drag-Ereignis mit dem Aktionstyp
ACTION_DROP
auslöst, sendet das System bei Bedarf ein Drag-Ereignis mit dem AktionstypACTION_DRAG_ENDED
, um anzuzeigen, dass der Drag-and-drop-Vorgang beendet ist. Das geschieht unabhängig davon, wo der Nutzer den Schatten loslässt. Das Ereignis wird an alle Listener gesendet, die zum Empfang von Drag-Ereignissen registriert sind, auch wenn der Listener auch das EreignisACTION_DROP
empfängt.
Die einzelnen Schritte werden im Abschnitt Drag-and-drop-Vorgang ausführlicher beschrieben.
Drag-Events
Das System sendet ein Drag-Ereignis in Form eines DragEvent
-Objekts, das einen Aktionstyp enthält, der beschreibt, was beim Drag-and-drop-Vorgang passiert. Je nach Aktionstyp kann das Objekt auch andere Daten enthalten.
Drag-Event-Listener erhalten das DragEvent
-Objekt. Um den Aktionstyp abzurufen, rufen Listener DragEvent.getAction()
auf.
Es gibt sechs mögliche Werte, die durch Konstanten in der Klasse DragEvent
definiert sind. Sie werden in Tabelle 1 beschrieben:
Tabelle 1 Aktionstypen für DragEvent
Aktionstyp | Bedeutung |
---|---|
ACTION_DRAG_STARTED |
Die Anwendung ruft startDragAndDrop() auf und erhält einen Schatten, der beim Ziehen zu sehen ist. Wenn der Listener weiterhin Drag-Ereignisse für diese Aktion erhalten möchte, muss er dem System den booleschen Wert true zurückgeben.
|
ACTION_DRAG_ENTERED |
Der Schatten des Ziehens betritt den Begrenzungsrahmen des View des Drag-Event-Listeners. Dies ist der erste Ereignisaktionstyp, den der Listener empfängt, wenn der Schatten des Ziehvorgangs den Begrenzungsrahmen betritt.
|
ACTION_DRAG_LOCATION |
Nach einem ACTION_DRAG_ENTERED -Ereignis befindet sich der Schatten des Ziehens noch innerhalb des Begrenzungsrahmens der View des Drag-Ereignis-Listeners.
|
ACTION_DRAG_EXITED |
Nach einem ACTION_DRAG_ENTERED - und mindestens einem ACTION_DRAG_LOCATION -Ereignis bewegt sich der Schatten des Drag-Events außerhalb des Begrenzungs-Quadranten der View des Drag-Event-Listeners.
|
ACTION_DROP |
Der Schatten wird über der View des Drag-Event-Listeners freigegeben. Dieser Aktionstyp wird nur an den Listener eines View -Objekts gesendet, wenn der Listener als Reaktion auf das ACTION_DRAG_STARTED -Drag-Ereignis den booleschen Wert true zurückgibt. Dieser Aktionstyp wird nicht gesendet, wenn der Nutzer den Schatten des Ziehvorgangs über einem View loslässt, dessen Listener nicht registriert ist, oder wenn der Nutzer den Schatten des Ziehvorgangs über etwas loslässt, das nicht zum aktuellen Layout gehört.
Der Listener gibt den booleschen Wert |
ACTION_DRAG_ENDED |
Das System beendet den Drag-and-drop-Vorgang. Diesem Aktionstyp geht nicht unbedingt ein ACTION_DROP -Ereignis voraus. Wenn das System eine ACTION_DROP sendet, bedeutet der Empfang des Aktionstyps ACTION_DRAG_ENDED nicht, dass die Auslieferung erfolgreich war. Der Listener muss getResult() aufrufen, wie in Tabelle 2 dargestellt, um den Wert abzurufen, der als Antwort auf ACTION_DROP zurückgegeben wird. Wenn kein ACTION_DROP -Ereignis gesendet wird, gibt getResult() false zurück.
|
Das DragEvent
-Objekt enthält auch die Daten und Metadaten, die Ihre Anwendung dem System beim Aufruf von startDragAndDrop()
zur Verfügung stellt. Einige der Daten sind nur für bestimmte Aktionstypen gültig, wie in Tabelle 2 zusammengefasst. Weitere Informationen zu Ereignissen und den zugehörigen Daten finden Sie im Abschnitt Drag-and-drop-Vorgang.
Tabelle 2 Gültige DragEvent-Daten nach Aktionstyp
getAction() -Wert |
getClipDescription() -Wert |
getLocalState() -Wert |
getX() -Wert |
getY() -Wert |
getClipData() -Wert |
getResult() -Wert |
---|---|---|---|---|---|---|
ACTION_DRAG_STARTED |
✓ | ✓ | ||||
ACTION_DRAG_ENTERED |
✓ | ✓ | ||||
ACTION_DRAG_LOCATION |
✓ | ✓ | ✓ | ✓ | ||
ACTION_DRAG_EXITED |
✓ | ✓ | ||||
ACTION_DROP |
✓ | ✓ | ✓ | ✓ | ✓ | |
ACTION_DRAG_ENDED |
✓ | ✓ |
Die DragEvent
-Methoden getAction()
, describeContents()
, writeToParcel()
und toString()
geben immer gültige Daten zurück.
Wenn eine Methode keine gültigen Daten für einen bestimmten Aktionstyp enthält, wird je nach Ergebnistyp null
oder 0 zurückgegeben.
Drag-Schatten
Während eines Drag-and-drop-Vorgangs zeigt das System ein Bild an, das der Nutzer zieht. Beim Verschieben von Daten steht dieses Bild für die Daten, die gezogen werden. Bei anderen Vorgängen stellt das Bild einen Aspekt des Ziehens dar.
Das Bild wird als Drag-Shadow bezeichnet. Sie erstellen sie mit Methoden, die Sie für ein View.DragShadowBuilder
-Objekt deklarieren. Sie übergeben den Builder an das System, wenn Sie mit startDragAndDrop()
einen Drag-and-drop-Vorgang starten. Im Rahmen der Antwort auf startDragAndDrop()
ruft das System die in View.DragShadowBuilder
definierten Callback-Methoden auf, um einen Schatten zu erhalten.
Die Klasse View.DragShadowBuilder
hat zwei Konstruktoren:
View.DragShadowBuilder(View)
Dieser Konstruktor akzeptiert alle
View
-Objekte Ihrer Anwendung. Der Konstruktor speichert dasView
-Objekt imView.DragShadowBuilder
-Objekt, damit die Callbacks darauf zugreifen können, um den Schatten zu erstellen. Die Ansicht muss keineView
sein, die der Nutzer auswählt, um den Ziehvorgang zu starten.Wenn Sie diesen Konstruktor verwenden, müssen Sie
View.DragShadowBuilder
nicht erweitern oder seine Methoden überschreiben. Standardmäßig wird ein Schatten angezeigt, der derView
entspricht, die Sie als Argument übergeben. Er ist zentriert unter der Stelle, an der der Nutzer den Bildschirm berührt.View.DragShadowBuilder()
Wenn Sie diesen Konstruktor verwenden, ist im
View.DragShadowBuilder
-Objekt keinView
-Objekt verfügbar. Das Feld ist aufnull
gesetzt. Sie müssenView.DragShadowBuilder
erweitern und seine Methoden überschreiben, da sonst ein unsichtbarer Schatten entsteht. Das System gibt keinen Fehler aus.
Die Klasse View.DragShadowBuilder
hat zwei Methoden, die zusammen den Schatten beim Ziehen erzeugen:
onProvideShadowMetrics()
Das System ruft diese Methode sofort nach dem Aufrufen von
startDragAndDrop()
auf. Verwenden Sie die Methode, um die Abmessungen und den Berührungspunkt des Schattens an das System zu senden. Die Methode hat zwei Parameter:outShadowSize
:einPoint
-Objekt. Die Breite des Schattens wird inx
und die Höhe iny
angegeben.outShadowTouchPoint
:einPoint
-Objekt. Der Touchpoint ist die Stelle innerhalb des Schattens, die während des Ziehens unter dem Finger des Nutzers sein muss. Die X-Position wird inx
und die Y-Position iny
eingegeben.onDrawShadow()
Unmittelbar nach dem Aufruf von
onProvideShadowMetrics()
ruft das SystemonDrawShadow()
auf, um den Schatten zu erstellen. Die Methode hat ein einziges Argument, einCanvas
-Objekt, das das System aus den Parametern erstellt, die Sie inonProvideShadowMetrics()
angeben. Die Methode zeichnet den Schatten des Objekts auf dem angegebenenCanvas
.
Halten Sie die Größe des Schattens beim Ziehen klein, um die Leistung zu verbessern. Für einen einzelnen Artikel können Sie ein Symbol verwenden. Bei einer Auswahl mehrerer Elemente sollten Sie Symbole in einem Stapel verwenden, anstatt vollständige Bilder auf dem Bildschirm zu verteilen.
Event-Listener und Callback-Methoden ziehen
Ein View
empfängt Drag-Events mit einem Drag-Ereignis-Listener, der View.OnDragListener
implementiert, oder mit der onDragEvent()
-Callback-Methode der Ansicht. Wenn das System die Methode oder den Listener aufruft, wird ein DragEvent
-Argument übergeben.
In den meisten Fällen ist die Verwendung eines Listeners vorzuziehen. Beim Entwerfen von UIs werden View
-Klassen in der Regel nicht als Unterklasse erstellt. Wenn Sie jedoch die Rückrufmethode verwenden, müssen Sie Unterklassen erstellen, um die Methode zu überschreiben. Im Vergleich dazu können Sie eine Listener-Klasse implementieren und dann mit mehreren verschiedenen View
-Objekten verwenden. Sie können sie auch als anonyme Inline-Klasse oder Lambda-Ausdruck implementieren. Rufen Sie setOnDragListener()
auf, um den Listener für ein View
-Objekt festzulegen.
Alternativ können Sie die Standardimplementierung von onDragEvent()
ändern, ohne die Methode zu überschreiben. Legen Sie für eine Ansicht einen OnReceiveContentListener
fest. Weitere Informationen finden Sie unter setOnReceiveContentListener()
.
Die Methode onDragEvent()
führt dann standardmäßig Folgendes aus:
- Gibt in Antwort auf den Aufruf von
startDragAndDrop()
den Wert „wahr“ zurück. Ruft
performReceiveContent()
auf, wenn die per Drag-and-drop eingefügten Daten in die Ansicht abgelegt werden. Die Daten werden alsContentInfo
-Objekt an die Methode übergeben. Die Methode ruft dieOnReceiveContentListener
auf.Gibt „wahr“ zurück, wenn die per Drag-and-drop eingefügten Daten in die Ansicht abgelegt werden und
OnReceiveContentListener
einen Teil des Inhalts beansprucht.
Definieren Sie die OnReceiveContentListener
, um die Daten speziell für Ihre App zu verarbeiten. Verwenden Sie für die Abwärtskompatibilität bis API-Level 24 die Jetpack-Version von OnReceiveContentListener
.
Sie können einen Ereignis-Listener für das Ziehen und eine Callback-Methode für ein View
-Objekt haben. In diesem Fall ruft das System zuerst den Listener auf. Das System ruft die Callback-Methode nur auf, wenn der Listener false
zurückgibt.
Die Kombination der Methode onDragEvent()
und View.OnDragListener
ist analog zur Kombination von onTouchEvent()
und View.OnTouchListener
, die bei Touch-Ereignissen verwendet wird.