Ziehen und Wischen Sie in RecyclerView. Teil 1: ItemTouchHelper

Ursprünglicher Autor: Paul Burke
  • Übersetzung
  • Tutorial

Ziehen und Wischen Sie in RecyclerView.  Teil 1: ItemTouchHelper


Es gibt viele Tutorials, Bibliotheken sowie Drag & Drop- und Swipe-to-Dismiss-Implementierungen in Android mit RecyclerView. Die meisten von ihnen verwenden immer noch den veralteten View.OnDragListener und den von Roman Nurik entwickelten SwipeToDismiss- Ansatz . Es gibt zwar bereits neue und effektivere Methoden. Nur sehr wenige Verwendung der neuesten API, die sich oft auf GestureDetectorsund onInterceptTouchEventoder andere komplexere Implementierung. Tatsächlich gibt es eine sehr einfache Möglichkeit, diese Funktionen hinzuzufügen RecyclerView. Dies erfordert nur eine Klasse, die auch Teil der Android Support Library ist.


ItemTouchHelper


ItemTouchHelper - ist ein leistungsfähiges Werkzeug , das sich um alles kümmert , dass Bedürfnisse hinzuzufügen Funktionen getan werden per Drag & Drop , und Swipe-to-abtun in RecyclerView. Dieses Dienstprogramm ist eine Unterklasse von RecyclerView.ItemDecoration , mit der es einfach ist, fast jeden vorhandenen LayoutManagerAdapter hinzuzufügen . Es funktioniert auch mit Elementanimationen und bietet die Möglichkeit, Elemente eines Typs per Drag & Drop an eine andere Stelle in der Liste zu ziehen und vieles mehr. In diesem Artikel werde ich eine einfache Implementierung demonstrieren ItemTouchHelper. Später werden wir im Rahmen dieser Artikelserie den Geltungsbereich erweitern und andere Optionen in Betracht ziehen.


Hinweis Möchten Sie das Ergebnis sofort sehen? Schauen Sie sich Github: Android-ItemTouchHelper-Demo an . Das erste Commit bezieht sich auf diesen Artikel. Demo- .apkDatei kann hier heruntergeladen werden .


Beispiel


Anpassung


Zuerst müssen wir konfigurieren RecyclerView. Wenn Sie dies noch nicht getan haben, fügen Sie die Abhängigkeit RecyclerViewzu Ihrer Datei hinzu build.gradle.


compile 'com.android.support:recyclerview-v7:22.2.0'

ItemTouchHelperfunktioniert mit fast allen RecyclerView.Adapterund LayoutManager, aber dieser Artikel basiert auf Beispielen, die diese Dateien verwenden .


Verwenden von ItemTouchHelper und ItemTouchHelper.Callback


Zur Verwendung ItemTouchHelpermüssen Sie einen ItemTouchHelper.Callback erstellen . Dies ist eine Oberfläche, mit der Sie die Bewegung verfolgen ( engl. Move ) und wischen ( engl. Swipe) können. Außerdem können Sie hier den Status der ausgewählten viewKomponente 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 das in der Praxis funktioniert, werden wir alles selbst machen.


Die Hauptfunktionen der Schnittstelle, die neu definiert werden müssen, um die grundlegenden Funktionen von Drag & Drop und Swipe-to-Dismiss zu umfassen :


getMovementFlags(RecyclerView, ViewHolder)
onMove(RecyclerView, ViewHolder, ViewHolder)
onSwiped(ViewHolder, int)

Wir werden auch verschiedene Hilfsmethoden anwenden:


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);
}

ItemTouchHelperermöglicht es Ihnen, die Richtung des Ereignisses leicht zu bestimmen. Sie müssen die Methode überschreiben, getMovementFlags()um anzugeben, welche Richtungen zum Ziehen und Ablegen unterstützt werden. Verwenden Sie die Hilfsmethode, um Rückgabeflags zu erstellen ItemTouchHelper.makeMovementFlags(int, int). In diesem Beispiel aktivieren wir Drag & Drop in beide Richtungen.


@Override
public boolean isLongPressDragEnabled() {
    return true;
}

ItemTouchHelperkann nur für Drag & Drop ohne Wischfunktion verwendet werden (oder umgekehrt), daher müssen Sie genau angeben, welche Funktionen unterstützt werden sollen. Die Methode isLongPressDragEnabled()muss einen Wert zurückgeben true, der Drag & Drop nach einem langen Klick auf ein Element unterstützt RecyclerView. Alternativ können Sie die Methode aufrufen ItemTouchHelper.startDrag(RecyclerView.ViewHolder), um Drag & Drop manuell zu starten. Wir werden diese Option später prüfen.


@Override
public boolean isItemViewSwipeEnabled() {
    return true;
}

viewGeben Sie einfach den Wert trueaus der Methode zurück, um das Austauschen zu aktivieren, nachdem Sie eine beliebige Stelle in der Komponente berührt haben isItemViewSwipeEnabled(). Alternativ können Sie die Methode aufrufen ItemTouchHelper.startSwipe(RecyclerView.ViewHolder), um das Wischen manuell zu starten.


Die folgenden beiden Methoden onMove()und onSwiped()sind erforderlich, um Sie über Datenaktualisierungen zu informieren. Zunächst erstellen wir eine Schnittstelle, über die diese Ereignisse über eine Kette von Aufrufen übertragen werden können.


ItemTouchHelperAdapter.java


public interface ItemTouchHelperAdapter {
    void onItemMove(int fromPosition, int toPosition);
    void onItemDismiss(int position);
}

Am einfachsten ist es, wenn der RecyclerListAdapter den Listener implementiert.


public class RecyclerListAdapter extends 
        RecyclerView.Adapter 
        implements ItemTouchHelperAdapter {
// ... код из [примера](https://gist.github.com/iPaulPro/2216ea5e14818056cfcc#file-recyclerlistadapter-java)
@Override
public void onItemDismiss(int position) {
    mItems.remove(position);
    notifyItemRemoved(position);
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
    if (fromPosition < toPosition) {
        for (int i = fromPosition; i < toPosition; i++) {
            Collections.swap(mItems, i, i + 1);
        }
    } else {
        for (int i = fromPosition; i > toPosition; i--) {
            Collections.swap(mItems, i, i - 1);
        }
    }
    notifyItemMoved(fromPosition, toPosition);
    return true;
}

Es ist wichtig , die Methoden aufrufen notifyItemRemoved()und notifyItemMoved()den Adapter , um die Änderungen zu sehen. Es sollte auch beachtet werden, dass wir die Position des Elements jedes Mal ändern, wenn die view-Komponente in einen neuen Index verschoben wird, und nicht ganz am Ende der Bewegung ("Drop" -Ereignis) .


Jetzt können wir zur Schöpfung zurückkehren SimpleItemTouchHelperCallback, da wir die Methoden onMove()und immer noch neu definieren müssen onSwiped(). 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());
}

Folglich sollte die Klasse Callbackungefähr 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 fertig ist, können wir ItemTouchHelpereine Methode erstellen und aufrufen attachToRecyclerView(RecyclerView)(zum Beispiel in MainFragment.java ):


ItemTouchHelper.Callback callback = 
    new SimpleItemTouchHelperCallback(adapter);
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(recyclerView);

Nach dem Start sollten Sie Folgendes erhalten:


Ergebnis


Fazit


Dies ist die einfachste Implementierung ItemTouchHelper. Allerdings können Sie feststellen , dass Sie nicht über eine Drittanbieter - Bibliothek verwenden müssen , um Standardaktionen zu implementieren Drag & Drop und Swipe-to-abtun in RecyclerView. Im nächsten Teil werden wir dem Aussehen der Elemente beim Ziehen und Ablegen mehr Aufmerksamkeit schenken.


Quellcode


Ich habe ein Projekt auf GitHub 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: Controller, Raster und benutzerdefinierte Animationen per Drag & Drop


Jetzt auch beliebt: