Wischen Sie für RecyclerView zum Schließen [geschlossen]

116

Früher habe ich die SwipeToDismiss- Bibliothek verwendet, aber jetzt versuche ich, auf RecyclerView zu migrieren, und die Dinge sind nicht so offensichtlich. Kennen Sie Ersatz für diese Bibliothek? Irgendwelche Ideen, wie man es von Grund auf umsetzt?

Viktor Yakunin
quelle
1
Ich habe eine kleine Bibliothek erstellt, die ItemTouchHelper verwendet, um die Erstellung von Gesten für die Recycling-Ansicht zu vereinfachen. Sie finden sie hier. Github.com/olmur/rvtools
Olexii Muraviov

Antworten:

336

Ab Version 22.2.0 hat das Android-Supportteam eine ItemTouchHelperKlasse hinzugefügt, die das Wischen zum Entlassen und Ziehen und Ablegen ziemlich einfach macht. Dies ist möglicherweise nicht so umfassend wie einige der Bibliotheken, aber es kommt direkt vom Android-Team.

  • Aktualisieren Sie Ihr build.gradle, um v22.2. + Der RecyclerView-Bibliothek zu importieren

    compile 'com.android.support:recyclerview-v7:22.2.+'
  • Instanziieren Sie einen ItemTouchHelper mit einem geeigneten SimpleCallback

    ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
        [...]
        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
            //Remove swiped item from list and notify the RecyclerView
        }
    };
    
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
    

    ** Beachten Sie, dass der SimpleCallback die Richtungen berücksichtigt, in denen Sie Drag & Drop aktivieren möchten, und die Richtungen, in denen Sie das Wischen aktivieren möchten.

  • An Ihre RecyclerView anhängen

    itemTouchHelper.attachToRecyclerView(recyclerView);
jmcdale
quelle
7
Wie kann man einen Index des geklauten Gegenstands erhalten?
MaTTo
37
@Orochi Durch Aufrufen von getAdapterPosition () auf dem viewHolder.
SqueezyMo
1
Sie haben offensichtlich nicht zu viel über das Design dieser Komponente nachgedacht. Es funktioniert nur mit einem RecyclerView. Swipe-to-Entlass gibt es für Dinge wie Snackbars. Eine allgemeinere Komponente, die mit jeder Ansicht verwendet werden könnte, wäre willkommener gewesen.
AndroidDev
4
Was ist, wenn ich den Fall behandeln möchte, wenn der Benutzer teilweise wischt und dann die Ansicht wieder in Position zieht? Anscheinend ist dies nicht möglich (?) BEARBEITEN: OK, es ist möglich, aber es gibt einen sehr kleinen Spielraum, in dem Sie bleiben können, bevor die Ansicht bei der Veröffentlichung gewischt wird. Irgendein Vorschlag?
Matteo
2
@Matteo: Implementieren Sie ItemTouchHelper.Callback und überschreiben Sie getSwipeThreshold ()
Sofi Software LLC
35
 ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            return false;
        }

        @Override
        public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
            final int position = viewHolder.getAdapterPosition(); //get position which is swipe

            if (direction == ItemTouchHelper.LEFT) {    //if swipe left

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); //alert for confirm to delete
                builder.setMessage("Are you sure to delete?");    //set message

                builder.setPositiveButton("REMOVE", new DialogInterface.OnClickListener() { //when click on DELETE
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        adapter.notifyItemRemoved(position);    //item removed from recylcerview
                        sqldatabase.execSQL("delete from " + TABLE_NAME + " where _id='" + (position + 1) + "'"); //query for delete
                        list.remove(position);  //then remove item

                        return;
                    }
                }).setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {  //not removing items if cancel is done
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        adapter.notifyItemRemoved(position + 1);    //notifies the RecyclerView Adapter that data in adapter has been removed at a particular position.
                        adapter.notifyItemRangeChanged(position, adapter.getItemCount());   //notifies the RecyclerView Adapter that positions of element in adapter has been changed from position(removed element index to end of list), please update it.
                        return;
                    }
                }).show();  //show alert dialog
            }
        }
    };
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
    itemTouchHelper.attachToRecyclerView(recyclerView); //set swipe to recylcerview

Hier im Code wird, wenn der Benutzer nach links wischt, AlertDialog angezeigt. Wenn der Benutzer ENTFERNEN auswählt, wird das Element aus der Datenbank gelöscht und die Recycling-Ansicht aktualisiert. Wenn der Benutzer die Option ABBRECHEN auswählt, ist die Recycling-Ansicht unverändert.

Khyati Fatania
quelle
funktioniert gut .. schöne Antwort.
Sagar Chavada
Genial! So einfach zu implementieren
Dianakarenms
1
Sie brauchen die Richtungsprüfung nicht wirklich, if (direction == ItemTouchHelper.LEFT) // if swipe leftda ItemTouchHelper.SimpleCallbacksie nur auf diese Wischrichtung beschränkt ist. Wenn Sie dann ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)und dann nach links und rechts wischen möchten, müssen Sie die Richtung überprüfen.
Jacko
1
Ich habe festgestellt, dass durch Klicken außerhalb des AlertDialogs der Dialog abgebrochen wurde, das zurückgewischte Element jedoch nicht platziert wurde. Sie können dies erfassen, indem Sie dem BuilderAlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // stuff to put the item back } });
Jacko
1
+1 Funktioniert gut. Ich fand, dass ich adapter.notifyItemChanged(position);den geklauten Gegenstand zurückgebracht habe, anstatt notifyItemRemoved- was imho logischer ist.
Winwaed
14

Vielleicht könnten Sie diese Bibliothek ausprobieren:

https://github.com/daimajia/AndroidSwipeLayout

Update: Ich habe gerade eine weitere gute Bibliothek gefunden, die Sie mit RecyclerView verwenden können:

https://github.com/hudomju/android-swipe-to-dismiss-undo

Pierpaolo Paolini
quelle
Ich habe meine eigene Implementierung ähnlich der von github.com/krossovochkin/Android-SwipeToDismiss-RecyclerView erstellt . Die einzige Voraussetzung war, Toast mit der Schaltfläche "Rückgängig" anzuzeigen, die in Ihrer Bibliothek nicht behandelt wird.
Viktor Yakunin
1
Die Bibliothek von Daimajia unterstützt die Funktion zum Wischen zum Entlassen nicht.
ungefähr am
@raveN Ich habe gerade meine Antwort aktualisiert.
Pierpaolo Paolini
2

Diese Bibliothek kann hilfreich sein. Sie können sie undoim OnDissmissEinsatz implementierensupertoast

xcodebuild
quelle
Hey, ich werde es versuchen! Basiert es auf dem von Pierpaolo beantworteten?
Junge
Es ist nur eine OnTouchListener Inspiration von diesem
xcodebuild
2

Ich habe die SwipeToDeleteRV- Bibliothek geschrieben, die die Funktion zum Wischen zum Löschen und Rückgängigmachen in Recycler-Ansichten unterstützt. Es basiert auf ItemTouchHelper und ist sehr einfach zu bedienen.

Ich hoffe, es kann für jemanden hilfreich sein, der mit denselben Problemen konfrontiert ist.

Als Beispiel können Sie Ihre Recycler-Ansicht in einem XML-Layout wie gewohnt sowie einige optionale Attribute definieren:

...
xmlns:stdrv="http://schemas.android.com/apk/res-auto"
...
<io.huannguyen.swipetodeleterv.STDRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
stdrv:border_color="@android:color/darker_gray" // specify things like border color, border width, etc.
stdrv:delete_view_background="#cccccc"
stdrv:delete_icon="@drawable/ic_archive"
stdrv:delete_icon_height="24dp"
stdrv:delete_icon_width="24dp"
stdrv:left_delete_icon_margin="32dp"
stdrv:delete_message="@string/delete_message"
stdrv:right_delete_icon_margin="32dp"
stdrv:delete_icon_color="#000000"
stdrv:has_border="true"/>

Alle stdrv-Attribute sind optional. Wenn Sie sie nicht angeben, werden die Standardwerte verwendet.

Erstellen Sie dann einen Adapter, der STDAdapter unterordnet, und rufen Sie den Superklassenkonstruktor auf. Etwas wie das:

public class SampleAdapter extends STDAdapter<String> {
public SampleAdapter(List<String> versionList) {
    super(versionList);
}

}}

Stellen Sie als Nächstes sicher, dass Sie die setupSwipeToDeleteMethode aufrufen, um die Funktion zum Streichen zum Löschen einzurichten.

mRecyclerView.setupSwipeToDelete(your_adapter_instance, swipe_directions);

swipe_directions ist die Richtung, in die Sie das Wischen von Elementen zulassen.

Beispiel:

// Get your recycler view from the XML layout
mRecyclerView = (STDRecyclerView) findViewById(R.id.recycler_view);
LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(layoutManager);
mAdapter = new SampleAdapter(versions);
// allow swiping in both directions (left-to-right and right-to-left)
mRecyclerView.setupSwipeToDelete(mAdapter, ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT);

Das ist es! Weitere erweiterte Einstellungen (z. B. unterschiedliche Löschmeldungen für unterschiedliche Elemente festlegen, Elemente vorübergehend und dauerhaft entfernen, ...) finden Sie auf der Projekt-Readme-Seite.

H. Nguyen
quelle