In den folgenden Abschnitten werden einige wichtige Konzepte für den Drag-and-drop-Prozess erläutert.
Drag-and-drop-Prozess
Der Drag-and-drop-Prozess besteht aus vier Schritten oder Zuständen: „Gestartet“, „Wird fortgesetzt“, „Abgebrochen“ und „Beendet“.
- Gestartet
Als Reaktion auf eine Drag-Geste eines Nutzers ruft Ihre Anwendung
startDragAndDrop()auf, um dem System mitzuteilen, dass ein Drag-and-drop-Vorgang gestartet werden soll. Die Argumente der Methode enthalten Folgendes:- Die zu ziehenden Daten
- Ein Callback zum Zeichnen des Drag-Schatten
- Metadaten, die die gezogenen Daten beschreiben
- Das System antwortet mit einem Rückruf an Ihre Anwendung, um einen Drag-Schatten zu erhalten. Das System zeigt dann den Drag-Schatten auf dem Gerät an.
- Als Nächstes sendet das System ein Drag-Ereignis mit dem Aktionstyp
ACTION_DRAG_STARTEDan den Drag-Ereignis Listener allerViewObjekte im aktuellen Layout. Damit weiterhin Drag-Ereignisse empfangen werden können, einschließlich eines möglichen Drop-Ereignisses, muss der Drag-Ereignis-Listenertruezurückgeben. Dadurch wird der Listener beim System registriert. Nur registrierte Listener empfangen weiterhin Drag-Ereignisse. An dieser Stelle können Listener auch das Erscheinungsbild ihres Drop-Ziel-View-Objekts ändern, um zu zeigen, dass die Ansicht ein Drop-Ereignis akzeptieren kann. - Wenn der Drag-Ereignis-Listener
falsezurückgibt, empfängt er keine Drag Ereignisse für den aktuellen Vorgang, bis das System ein Drag-Ereignis mit dem AktionstypACTION_DRAG_ENDEDsendet. Durch die Rückgabe vonfalseteilt 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 setzt das Ziehen fort. Wenn sich der Drag-Schatten mit dem Begrenzungsrahmen eines Drop-Ziels überschneidet, sendet das System ein oder mehrere Drag-Ereignisse an den Drag-Ereignis-Listener des Ziels. Der Listener kann das Erscheinungsbild des Drop-Ziel-
View-Objekts als Reaktion auf das Ereignis ändern. Wenn das Ereignis beispielsweise angibt, dass der Drag-Schatten in den Begrenzungsrahmen des Drop- Ziels eintritt (AktionstypACTION_DRAG_ENTERED), kann der Listener reagieren, indem er dieViewhervorhebt. - Abgebrochen
- Der Nutzer lässt den Drag-Schatten innerhalb des Begrenzungsrahmens eines Drop-Ziels los. Das System sendet dem Listener des Drop-Ziels ein Drag-Ereignis mit Aktion
typ
ACTION_DROP. Das Drag-Ereignisobjekt enthält die Daten, die beim Aufruf vonstartDragAndDrop()an das System übergeben werden, wodurch der Vorgang gestartet wird. Der Listener muss den booleschen Werttruean das System zurückgeben, wenn er die abgelegten Daten erfolgreich verarbeitet hat. Dieser Schritt erfolgt nur, wenn der Nutzer den Drag-Schatten innerhalb des Begrenzungsrahmens einerViewablegt, deren Listener für den Empfang von Drag-Ereignissen registriert ist (ein Drop-Ziel). Wenn der Nutzer den Drag-Schatten in einer anderen Situation loslässt, wird keinACTION_DROP-Drag-Ereignis gesendet. - Beendet
Nachdem der Nutzer den Drag-Schatten losgelassen hat und nachdem das System
gegebenenfalls ein Drag-Ereignis mit dem Aktionstyp
ACTION_DROPgesendet hat, sendet das System ein Drag-Ereignis mit dem AktionstypACTION_DRAG_ENDED, um anzugeben, dass der Drag-and-drop-Vorgang beendet ist. Dies geschieht unabhängig davon, wo der Nutzer den Drag-Schatten loslässt. Das Ereignis wird an alle Listener gesendet, die für den Empfang von Drag-Ereignissen registriert sind, auch wenn der Listener auch dasACTION_DROP-Ereignis empfängt.
Jeder dieser Schritte wird im Abschnitt Drag-and-drop-Vorgang ausführlicher beschrieben.
Drag-Ereignisse
Das System sendet ein Drag-Ereignis in Form eines DragEvent-Objekts, das einen Aktionstyp enthält, der beschreibt, was im Drag-and-drop-Prozess geschieht. Je nach Aktionstyp kann das Objekt auch andere Daten enthalten.
Drag-Ereignis-Listener empfangen das DragEvent-Objekt. Um den Aktionstyp zu erhalten,
rufen Listener
DragEvent.getAction() auf.
Es gibt sechs mögliche Werte, die durch Konstanten in der DragEvent-Klasse definiert werden und in Tabelle 1 beschrieben sind:
Tabelle 1. DragEvent-Aktionstypen
| Aktionstyp | Bedeutung |
|---|---|
ACTION_DRAG_STARTED |
Die Anwendung ruft startDragAndDrop() auf und erhält
einen Drag-Schatten. Wenn der Listener weiterhin Drag-Ereignisse für diesen Vorgang empfangen möchte, muss er den booleschen Wert true an das System zurückgeben.
|
ACTION_DRAG_ENTERED |
Der Drag-Schatten tritt in den Begrenzungsrahmen des Drag-Ereignis-Listeners ein.
View. Dies ist der erste Ereignisaktionstyp, den der Listener
empfängt, wenn der Drag-Schatten in den Begrenzungsrahmen eintritt.
|
ACTION_DRAG_LOCATION |
Nach einem
ACTION_DRAG_ENTERED Ereignis befindet sich der Drag-Schatten weiterhin
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 Drag-Schatten
außerhalb des Begrenzungsrahmens der
View des Drag-Ereignis-Listeners.
|
ACTION_DROP |
Der Drag-Schatten wird über der
View des Drag-Ereignis-Listeners losgelassen. Dieser Aktionstyp wird nur dann 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 Drag-Schatten über einer View
loslässt, deren Listener nicht registriert ist, oder wenn der Nutzer den Drag
Schatten über etwas loslässt, das nicht Teil des aktuellen Layouts ist.
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 ein ACTION_DROP-Ereignis sendet, bedeutet der Empfang des
ACTION_DRAG_ENDED Aktionstyps nicht, dass der
Drop erfolgreich war. Der Listener muss
getResult(),
aufrufen, wie in Tabelle 2 gezeigt, um den Wert zu erhalten, der
als Reaktion 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 beim Aufruf von startDragAndDrop() an das System übergibt. 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 für einen bestimmten Aktionstyp keine gültigen Daten enthält, gibt sie je nach Ergebnistyp null oder 0 zurück.
Drag-Schatten
Während eines Drag-and-drop-Vorgangs zeigt das System ein Bild an, das der Nutzer zieht. Bei der Datenübertragung stellt dieses Bild die gezogenen Daten dar. Bei anderen Vorgängen stellt das Bild einen Aspekt des Drag-Vorgangs dar.
Das Bild wird Drag-Schatten genannt. Sie erstellen es mit Methoden, die Sie für
ein
View.DragShadowBuilder
Objekt deklarieren. Sie übergeben den Builder an das System, wenn Sie einen Drag-and-drop-Vorgang mit startDragAndDrop() starten. Als Teil der Antwort auf startDragAndDrop() ruft das System die Callback-Methoden auf, die Sie in View.DragShadowBuilder definieren, um einen Drag-Schatten zu erhalten.
Die View.DragShadowBuilder-Klasse hat zwei Konstruktoren:
View.DragShadowBuilder(View)Dieser Konstruktor akzeptiert alle Objekte Ihrer Anwendung
View. Der Konstruktor speichert dasViewObjekt imView.DragShadowBuilderObjekt, damit die Callbacks darauf zugreifen können, um den Drag-Schatten zu erstellen. Die Ansicht muss keineViewsein, die der Nutzer auswählt, um den Drag-Vorgang zu starten.Wenn Sie diesen Konstruktor verwenden, müssen Sie
View.DragShadowBuildernicht erweitern oder seine Methoden überschreiben. Standardmäßig erhalten Sie einen Drag-Schatten, der genauso aussieht wie dieView, die Sie als Argument übergeben, 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 aufnullgesetzt. Sie müssenView.DragShadowBuildererweitern und seine Methoden überschreiben, da Sie sonst einen unsichtbaren Drag-Schatten erhalten. Das System löst keinen Fehler aus.
Die View.DragShadowBuilder-Klasse hat zwei Methoden, die zusammen den Drag-Schatten erstellen:
onProvideShadowMetrics()Das System ruft diese Methode sofort auf, nachdem Sie
startDragAndDrop()aufgerufen haben. Verwenden Sie die Methode, um die Abmessungen und den Touchpoint des Drag-Schatten an das System zu senden. Die Methode hat zwei Parameter:outShadowSize: einPointObjekt. Die Breite des Drag-Schatten wird inxund seine Höhe inyangegeben.outShadowTouchPoint: einPoint-Objekt. Der Touchpoint ist die Stelle innerhalb des Drag-Schatten, die während des Ziehens unter dem Finger des Nutzers liegen muss. Die X-Position wird inxund die Y-Position inyangegeben.onDrawShadow()Unmittelbar nach dem Aufruf von
onProvideShadowMetrics()ruft das SystemonDrawShadow()auf, um den Drag-Schatten zu erstellen. Die Methode hat ein einzelnes Argument, einCanvas-Objekt, das das System aus den Parametern erstellt, die Sie inonProvideShadowMetrics()angeben. Die Methode zeichnet den Drag-Schatten auf das bereitgestellteCanvas.
Um die Leistung zu verbessern, halten Sie die Größe des Drag-Schatten klein. Für ein einzelnes Element können Sie ein Symbol verwenden. Bei einer Auswahl mehrerer Elemente können Sie Symbole in einem Stapel verwenden, anstatt vollständige Bilder auf dem Bildschirm zu verteilen.
Drag-Ereignis-Listener und Callback-Methoden
Eine View empfängt Drag-Ereignisse 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 bereitgestellt.
In den meisten Fällen ist die Verwendung eines Listeners der Verwendung der Callback-Methode vorzuziehen. Beim Entwerfen von Benutzeroberflächen werden View-Klassen in der Regel nicht untergeordnet. Bei der Verwendung der Callback-Methode müssen Sie jedoch Unterklassen erstellen, um die Methode zu überschreiben. Im Vergleich dazu können Sie eine Listener-Klasse implementieren und sie dann mit mehreren verschiedenen View-Objekten verwenden. Sie können sie auch als anonyme Inline-Klasse oder Lambda-Ausdruck implementieren. Um den Listener für ein View-Objekt festzulegen, rufen Sie setOnDragListener() auf.
Alternativ können Sie die Standardimplementierung von onDragEvent() ändern, ohne die Methode zu überschreiben. Legen Sie einen
OnReceiveContentListener
für eine Ansicht fest. Weitere Informationen finden Sie unter
setOnReceiveContentListener().
Die Methode onDragEvent() führt standardmäßig Folgendes aus:
- Gibt als Reaktion auf den Aufruf von
startDragAndDrop()„true“ zurück. Ruft
performReceiveContent()auf, wenn die Drag-and-drop-Daten in der Ansicht abgelegt werden. Die Daten werden alsContentInfoObjekt an die Methode übergeben. Die Methode ruft denOnReceiveContentListenerauf.Gibt „true“ zurück, wenn die Drag-and-drop-Daten in der Ansicht abgelegt werden und der
OnReceiveContentListenereinen Teil des Inhalts verwendet.
Definieren Sie den OnReceiveContentListener, um die Daten speziell für Ihre
App zu verarbeiten. Für die Abwärtskompatibilität bis API-Level 24 verwenden Sie die Jetpack-Version von
OnReceiveContentListener.
Sie können einen Drag-Ereignis-Listener 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 onDragEvent() Methode und View.OnDragListener entspricht der Kombination der
onTouchEvent()
und View.OnTouchListener
, die bei Touch-Ereignissen verwendet wird.