
Es gibt viele Tutorials, Bibliotheken sowie Drag & Drop- und Swipe-to-Dism-Implementierungen in Android mit RecyclerView. Die meisten von ihnen verwenden immer noch den veralteten View.OnDragListener und den von Roman Nurik entwickelten SwipeToDismiss- Ansatz. Obwohl bereits neue und effektivere Methoden verfügbar sind. Nur sehr wenige verwenden die neuesten APIs und onInterceptTouchEvent
häufig auf GestureDetectors
und onInterceptTouchEvent
oder andere komplexere Implementierungen. Tatsächlich gibt es eine sehr einfache Möglichkeit, diese Funktionen zu RecyclerView
hinzuzufügen. Dies erfordert nur eine Klasse, die ebenfalls Teil der Android Support Library ist.
ItemTouchHelper
ItemTouchHelper ist ein leistungsstarkes Dienstprogramm, das sich um alles kümmert, was Sie tun müssen, um RecyclerView
Drag & Drop- und Swipe-to-Dism-Funktionen hinzuzufügen. Dieses Dienstprogramm ist eine Unterklasse von RecyclerView.ItemDecoration , mit der sich fast jeder vorhandene LayoutManager
und Adapter problemlos hinzufügen lässt. Es funktioniert auch mit Elementanimationen und bietet die Möglichkeit, Elemente eines Typs an eine andere Stelle in der Liste zu ziehen und dort abzulegen. In diesem Artikel werde ich eine einfache Implementierung von ItemTouchHelper
. Später, als Teil dieser Artikelserie, werden wir den Umfang erweitern und andere Optionen in Betracht ziehen.
Hinweis Möchten Sie das Ergebnis sofort sehen? Schauen Sie sich Github an: Android-ItemTouchHelper-Demo . Das erste Commit bezieht sich auf diesen Artikel. Demo .apk
Datei kann hier heruntergeladen werden .

Anpassung
Zuerst müssen wir die RecyclerView
konfigurieren. Wenn Sie dies noch nicht getan haben, fügen Sie die RecyclerView
Abhängigkeit zu Ihrer build.gradle
Datei hinzu.
compile 'com.android.support:recyclerview-v7:22.2.0'
ItemTouchHelper
funktioniert mit fast jedem RecyclerView.Adapter
und LayoutManager
. Dieser Artikel basiert jedoch auf Beispielen, die diese Dateien verwenden .
Verwenden von ItemTouchHelper und ItemTouchHelper.Callback
Um ItemTouchHelper
verwenden zu ItemTouchHelper
, müssen Sie einen ItemTouchHelper.Callback erstellen. Dies ist eine Schnittstelle, über die Sie die Aktionen von Bewegung ( dt. Bewegen) und Wischen ( dt. Wischen) verfolgen können. Außerdem können Sie hier den Status der ausgewählten view
steuern und die Standardanimation überschreiben. Es gibt eine Hilfsklasse , die Sie verwenden können, wenn Sie die Basisimplementierung SimpleCallback verwenden möchten . Aber um zu verstehen, wie dies in der Praxis funktioniert, werden wir alles selbst machen.
Die Hauptfunktionen der Benutzeroberfläche, die wir neu definieren müssen, um die Grundfunktionen von Drag & Drop und Swipe-to-Dism einzuschließen :
getMovementFlags(RecyclerView, ViewHolder) onMove(RecyclerView, ViewHolder, ViewHolder) onSwiped(ViewHolder, int)
Wir werden auch verschiedene Hilfsmethoden verwenden:
isLongPressDragEnabled() isItemViewSwipeEnabled()
Betrachten wir sie einzeln.
@Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); }
ItemTouchHelper
Sie leicht die Richtung eines Ereignisses bestimmen. Sie müssen die Methode getMovementFlags()
überschreiben, um anzugeben, welche Richtungen zum Ziehen und Ablegen unterstützt werden. Verwenden Sie zum Erstellen von Rückgabeflags die ItemTouchHelper.makeMovementFlags(int, int)
. In diesem Beispiel erlauben wir Drag & Drop in beide Richtungen.
@Override public boolean isLongPressDragEnabled() { return true; }
ItemTouchHelper
kann nur zum Ziehen und Ablegen ohne Wischfunktion verwendet werden (oder umgekehrt). Sie müssen daher genau angeben, welche Funktionen unterstützt werden sollen. Die Methode isLongPressDragEnabled()
muss true
, um Drag & Drop nach einem langen Klick auf das RecyclerView
Element zu unterstützen. Alternativ können Sie die ItemTouchHelper.startDrag(RecyclerView.ViewHolder)
Methode ItemTouchHelper.startDrag(RecyclerView.ViewHolder)
aufrufen, um das Ziehen manuell zu starten. Wir werden diese Option später prüfen.
@Override public boolean isItemViewSwipeEnabled() { return true; }
Um das Auspeitschen nach dem Berühren einer beliebigen Stelle in der view
zu aktivieren, geben Sie einfach true
von der Methode isItemViewSwipeEnabled()
. Alternativ können Sie die ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)
Methode ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)
aufrufen, um das ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)
manuell zu starten.
Die folgenden beiden Methoden, onMove()
und onSwiped()
, sind erforderlich, um Sie über onSwiped()
zu informieren. Zuerst erstellen wir eine Schnittstelle, über die diese Ereignisse entlang der Aufrufkette weitergeleitet werden können.
ItemTouchHelperAdapter.java
public interface ItemTouchHelperAdapter { void onItemMove(int fromPosition, int toPosition); void onItemDismiss(int position); }
Der einfachste Weg, dies zu tun, besteht darin, den Listener vom RecyclerListAdapter implementieren zu lassen.
public class RecyclerListAdapter extends RecyclerView.Adapter<ItemViewHolder> implements ItemTouchHelperAdapter {
Es ist sehr wichtig, die notifyItemRemoved()
und notifyItemMoved()
, damit der Adapter die Änderungen sieht. Es sollte auch beachtet werden, dass wir die Position des Elements jedes Mal ändern, wenn die view
auf einen neuen Index verschoben wird, und nicht ganz am Ende der Bewegung (das "Drop" -Ereignis) .
Jetzt können wir wieder SimpleItemTouchHelperCallback
, da wir die onMove()
und onSwiped()
noch überschreiben onMove()
. Fügen Sie zuerst den Konstruktor und das Feld für den Adapter hinzu:
private final ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback( ItemTouchHelperAdapter adapter) { mAdapter = adapter; }
Definieren Sie dann die verbleibenden Ereignisse neu und melden Sie dies dem Adapter:
@Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { mAdapter.onItemDismiss(viewHolder.getAdapterPosition()); }
Daher sollte die Callback
Klasse Callback
so aussehen:
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { private final ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { mAdapter = adapter; } @Override public boolean isLongPressDragEnabled() { return true; } @Override public boolean isItemViewSwipeEnabled() { return true; } @Override public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); } @Override public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) { mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(ViewHolder viewHolder, int direction) { mAdapter.onItemDismiss(viewHolder.getAdapterPosition()); } }
Wenn Callback bereit ist, können wir einen ItemTouchHelper
erstellen und die Methode attachToRecyclerView(RecyclerView)
aufrufen (z. B. in MainFragment.java ):
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter); ItemTouchHelper touchHelper = new ItemTouchHelper(callback); touchHelper.attachToRecyclerView(recyclerView);
Nach dem Start sollten Sie Folgendes erhalten:

Fazit
Dies ist die ItemTouchHelper
Implementierung von ItemTouchHelper
. Möglicherweise stellen Sie jedoch fest, dass Sie keine Bibliothek eines Drittanbieters verwenden müssen, um die standardmäßigen Drag & Drop- und Swipe-to-Dism-Aktionen in RecyclerView
zu implementieren. Im nächsten Teil werden wir dem Erscheinungsbild der Elemente zum Zeitpunkt des Drag & Drop mehr Aufmerksamkeit schenken.
Quellcode
Ich habe auf GitHub ein Projekt erstellt, um zu demonstrieren, was in dieser Artikelserie behandelt wird: Android-ItemTouchHelper-Demo . Das erste Commit bezieht sich hauptsächlich auf diesen Teil und ein bisschen auf das zweite .
→ Ziehen und wischen Sie in RecyclerView. Teil 2: Drag & Drop-Controller, Raster und benutzerdefinierte Animationen