Scorri per ignorare per RecyclerView [chiuso]


116

Ero abituato alla libreria SwipeToDismiss ma ora sto provando a migrare a RecyclerView e le cose non sono così ovvie, conosci qualche sostituzione per questa libreria? Qualche idea su come implementarlo da zero?


1
Ho creato una piccola libreria che utilizza ItemTouchHelper per rendere più facile la creazione di gesti per la revisione del riciclaggio, puoi trovarla qui github.com/olmur/rvtools
Olexii Muraviov

Risposte:


337

A partire dalla v22.2.0, il team di supporto di Android ha incluso una ItemTouchHelperclasse che semplifica lo scorrimento per chiudere e il trascinamento. Potrebbe non essere completo come alcune delle librerie là fuori, ma proviene direttamente dal team di Android.

  • Aggiorna il tuo build.gradle per importare la v22.2. + Della libreria RecyclerView

    compile 'com.android.support:recyclerview-v7:22.2.+'
  • Crea un'istanza di ItemTouchHelper con un SimpleCallback appropriato

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

    ** Notare che SimpleCallback prende le direzioni in cui si desidera abilitare il trascinamento e le direzioni in cui si desidera abilitare lo scorrimento.

  • Collega al tuo RecyclerView

    itemTouchHelper.attachToRecyclerView(recyclerView);

7
Come si può ottenere l'indice dell'elemento strisciato?
MaTTo

37
@Orochi Chiamando getAdapterPosition () nel file viewHolder.
SqueezyMo

1
Chiaramente non hanno pensato troppo al design di questo componente. Funziona solo con RecyclerView. Lo scorrimento per ignorare esiste per cose come snack bar. Un componente più generico che potrebbe essere utilizzato con qualsiasi vista sarebbe stato più gradito.
AndroidDev

4
E se volessi gestire il caso quando l'utente fa scorrere parzialmente il dito ma poi trascina di nuovo la vista in posizione? Apparentemente questo non è possibile (?) EDIT: ok, è possibile, ma c'è un margine minimo in cui puoi rimanere prima che la vista venga spostata al momento del rilascio. Qualche suggerimento?
Matteo

2
@Matteo: implementa ItemTouchHelper.Callback e sovrascrivi getSwipeThreshold ()
Sofi Software LLC

36
 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

Qui in Codice, se l'utente scorre verso sinistra, viene visualizzato AlertDialog e se l'utente seleziona RIMUOVI l'elemento viene eliminato dal database e recyclerview viene aggiornato e se l'utente seleziona ANNULLA, recyclerview è così com'è.


funziona bene .. bella risposta.
Sagar Chavada

Eccezionale! Così facile da implementare
dianakarenms

1
Non hai davvero bisogno del controllo della direzione if (direction == ItemTouchHelper.LEFT) // if swipe leftpoiché ItemTouchHelper.SimpleCallbackè limitato solo a quella direzione di scorrimento. Se vuoi scorrere verso sinistra e verso destra, ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)allora dovresti controllare la direzione.
Jacko

1
Ho scoperto che facendo clic al di fuori di AlertDialog si cancellava la finestra di dialogo ma non si inseriva nuovamente l'elemento che avevo fatto scorrere. Puoi catturarlo aggiungendo un OnCancelListener al 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 Funziona bene. Ho scoperto di aver adapter.notifyItemChanged(position);riportato indietro l'oggetto spostato, piuttosto che notifyItemRemoved- il che è più logico imho.
Winwaed

14

forse potresti provare questa libreria:

https://github.com/daimajia/AndroidSwipeLayout

Aggiornamento: ho appena trovato un'altra buona libreria che puoi utilizzare con RecyclerView:

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


Ho realizzato la mia implementazione simile a github.com/krossovochkin/Android-SwipeToDismiss-RecyclerView . L'unico requisito era mostrare Toast con il pulsante "Annulla", che non è incluso nella libreria.
Viktor Yakunin

1
La libreria di Daimajia non supporta la funzione di scorrimento per ignorare.
akohout

@raveN ho appena aggiornato la mia risposta.
Pierpaolo Paolini


2

Ho scritto la libreria SwipeToDeleteRV che supporta la funzione swipe-to-delete-undo nelle viste del riciclatore. È basato su ItemTouchHelper ed è molto facile da usare.

Spero che possa essere utile per qualcuno che affronta gli stessi problemi.

Ad esempio, puoi definire normalmente la visualizzazione del riciclatore in un layout XML, più alcuni attributi opzionali:

...
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"/>

Tutti gli attributi stdrv sono facoltativi. Se non li specifichi, verranno utilizzati quelli predefiniti.

Quindi crea un adattatore che sottoclasse STDAdapter, assicurati di chiamare il costruttore della super classe. Qualcosa come questo:

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

}

Quindi assicurati di effettuare una chiamata al setupSwipeToDeletemetodo per impostare la funzione di scorrimento per eliminare.

mRecyclerView.setupSwipeToDelete(your_adapter_instance, swipe_directions);

swipe_directions è la direzione in cui consenti lo scorrimento degli elementi.

Esempio:

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

Questo è tutto! Per impostazioni più avanzate (ad esempio, impostare messaggi di eliminazione diversi per elementi diversi, rimuovere elementi temporaneamente e permanentemente, ...) fare riferimento alla pagina readme del progetto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.