Wichtige Konzepte

Die Compose-Methode
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Informationen zum Verwenden von Drag-and-drop in Compose

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_STARTED an den Drag-Ereignis Listener aller View Objekte im aktuellen Layout. Damit weiterhin Drag-Ereignisse empfangen werden können, einschließlich eines möglichen Drop-Ereignisses, muss der Drag-Ereignis-Listener true zurü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 false zurückgibt, empfängt er keine Drag Ereignisse für den aktuellen Vorgang, bis das System ein Drag-Ereignis mit dem Aktionstyp ACTION_DRAG_ENDED sendet. Durch die Rückgabe von false 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 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 (Aktionstyp ACTION_DRAG_ENTERED ), kann der Listener reagieren, indem er die View hervorhebt.
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 von startDragAndDrop() an das System übergeben werden, wodurch der Vorgang gestartet wird. Der Listener muss den booleschen Wert true an 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 einer View ablegt, 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 kein ACTION_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_DROP gesendet hat, sendet das System ein Drag-Ereignis mit dem Aktionstyp ACTION_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 das ACTION_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 true zurück, wenn er den Drop erfolgreich verarbeitet hat. Andernfalls muss er false zurückgeben.

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 das View Objekt im View.DragShadowBuilder Objekt, damit die Callbacks darauf zugreifen können, um den Drag-Schatten zu erstellen. Die Ansicht muss keine View sein, die der Nutzer auswählt, um den Drag-Vorgang zu starten.

Wenn Sie diesen Konstruktor verwenden, müssen Sie View.DragShadowBuilder nicht erweitern oder seine Methoden überschreiben. Standardmäßig erhalten Sie einen Drag-Schatten, der genauso aussieht wie die View, 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 kein View-Objekt verfügbar. Das Feld ist auf null gesetzt. Sie müssen View.DragShadowBuilder erweitern 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: ein Point Objekt. Die Breite des Drag-Schatten wird in x und seine Höhe in y angegeben.

outShadowTouchPoint: ein Point-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 in x und die Y-Position in y angegeben.

onDrawShadow()

Unmittelbar nach dem Aufruf von onProvideShadowMetrics() ruft das System onDrawShadow() auf, um den Drag-Schatten zu erstellen. Die Methode hat ein einzelnes Argument, ein Canvas-Objekt, das das System aus den Parametern erstellt, die Sie in onProvideShadowMetrics() angeben. Die Methode zeichnet den Drag-Schatten auf das bereitgestellte Canvas.

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 als ContentInfo Objekt an die Methode übergeben. Die Methode ruft den OnReceiveContentListener auf.

  • Gibt „true“ zurück, wenn die Drag-and-drop-Daten in der Ansicht abgelegt werden und der OnReceiveContentListener einen 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.