Deslizar para descartar para RecyclerView [cerrado]

116

Solía usar la biblioteca SwipeToDismiss , pero ahora estoy tratando de migrar a RecyclerView y las cosas no son tan obvias, ¿conoce algún reemplazo para esta biblioteca? ¿Alguna idea de cómo implementarlo desde cero?

Viktor Yakunin
fuente
1
He creado una pequeña biblioteca que usa ItemTouchHelper para facilitar la creación de gestos para la vista de reciclaje, puede encontrarla aquí github.com/olmur/rvtools
Olexii Muraviov

Respuestas:

337

A partir de la v22.2.0, el equipo de soporte de Android ha incluido una ItemTouchHelperclase que hace que deslizar para descartar y arrastrar y soltar sea bastante simple. Es posible que esto no sea tan completo como algunas de las bibliotecas que existen, pero proviene directamente del equipo de Android.

  • Actualice su build.gradle para importar v22.2. + De la biblioteca RecyclerView

    compile 'com.android.support:recyclerview-v7:22.2.+'
  • Cree una instancia de ItemTouchHelper con un SimpleCallback apropiado

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

    ** Tenga en cuenta que SimpleCallback toma las direcciones en las que desea habilitar la función de arrastrar y soltar y las direcciones en las que desea habilitar el deslizamiento.

  • Adjuntar a su RecyclerView

    itemTouchHelper.attachToRecyclerView(recyclerView);
jmcdale
fuente
7
¿Cómo se puede obtener el índice de un artículo deslizado?
Martes
37
@Orochi Al llamar a getAdapterPosition () en el viewHolder.
SqueezyMo
1
Claramente, no pensaron demasiado en el diseño de este componente. Solo funciona con RecyclerView. Deslizar para descartar existe para cosas como bares. Hubiera sido más bienvenido un componente más genérico que pudiera usarse con cualquier vista.
AndroidDev
4
¿Qué sucede si quiero manejar el caso cuando el usuario desliza el dedo parcialmente pero luego arrastra la vista a su posición? Aparentemente, esto no es posible (?) EDITAR: ok, ES posible, pero hay un margen muy pequeño en el que puede permanecer antes de que la vista se deslice en el lanzamiento. ¿Cualquier sugerencia?
Matteo
2
@Matteo: Implementar ItemTouchHelper.Callback y anular 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

Aquí en Code, si el usuario desliza el dedo hacia la izquierda, se muestra AlertDialog y si el usuario selecciona REMOVE, el elemento se elimina de la base de datos y la vista de reciclaje se actualiza y si el usuario selecciona CANCELAR, la vista de reciclaje es como está.

Khyati Fatania
fuente
funcionando bien .. buena respuesta.
Sagar Chavada
¡Increíble! Tan fácil de implementar
dianakarenms
1
Realmente no necesita la verificación de dirección, if (direction == ItemTouchHelper.LEFT) // if swipe leftya que ItemTouchHelper.SimpleCallbackse limita solo a esa dirección de deslizamiento. Si desea deslizar hacia la izquierda y hacia la derecha, ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)deberá verificar la dirección.
Jacko
1
Descubrí que al hacer clic fuera de AlertDialog se cancelaba el cuadro de diálogo, pero no devolvía el elemento que había pasado. Puede capturar esto agregando 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 Funciona bien. Descubrí adapter.notifyItemChanged(position);que devolví el artículo deslizado, en lugar de notifyItemRemoved, lo cual es más lógico en mi humilde opinión.
winwaed el
14

tal vez podrías probar esta biblioteca:

https://github.com/daimajia/AndroidSwipeLayout

Actualización: acabo de encontrar otra buena biblioteca que puede usar con RecyclerView:

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

Pierpaolo Paolini
fuente
Hice mi propia implementación similar a github.com/krossovochkin/Android-SwipeToDismiss-RecyclerView . El único requisito era mostrar Toast con el botón "Deshacer", que no está cubierto en su lib.
Viktor Yakunin
1
La biblioteca de Daimajia no admite la función deslizar para descartar.
akohout
@raveN Acabo de actualizar mi respuesta.
Pierpaolo Paolini
2

Esta biblioteca puede ser útil . Puede implementar undoen OnDissmissusosupertoast

xcodebuild
fuente
¡Oye, voy a intentarlo! ¿Se basa en la contestada por Pierpaolo?
Niño
Es solo una OnTouchListener inspiración para esto
xcodebuild
2

Escribí la biblioteca SwipeToDeleteRV que admite la función de deslizar para eliminar y deshacer en las vistas de reciclador. Se basa en ItemTouchHelper y es muy fácil de usar.

Espero que pueda ser útil para alguien que enfrenta los mismos problemas.

Como ejemplo, puede definir su vista de reciclador en un diseño XML como normal, más algunos atributos opcionales:

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

Todos los atributos stdrv son opcionales. Si no los especifica, se usarán los predeterminados.

Luego cree un adaptador que subclases STDAdapter, asegúrese de llamar al constructor de superclase. Algo como esto:

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

}

A continuación, asegúrese de realizar una llamada al setupSwipeToDeletemétodo para configurar la función de deslizar para eliminar.

mRecyclerView.setupSwipeToDelete(your_adapter_instance, swipe_directions);

swipe_directions es la dirección en la que permite que se pasen los elementos.

Ejemplo:

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

¡Eso es! Para configuraciones más avanzadas (es decir, establecer diferentes mensajes de eliminación para diferentes elementos, eliminar elementos temporal y permanentemente, ...), consulte la página Léame del proyecto.

H. Nguyen
fuente