Balayez pour ignorer pour RecyclerView [fermé]

116

J'avais l'habitude d' utiliser la bibliothèque SwipeToDismiss mais maintenant j'essaye de migrer vers RecyclerView et les choses ne sont pas si évidentes, connaissez-vous des remplacements pour cette bibliothèque? Des idées pour le mettre en œuvre à partir de zéro?

Viktor Yakunin
la source
1
J'ai créé une petite bibliothèque qui utilise ItemTouchHelper pour faciliter la création de gestes pour recyclerview, vous pouvez la trouver ici github.com/olmur/rvtools
Olexii Muraviov

Réponses:

337

À partir de la version 22.2.0, l'équipe de support Android a inclus une ItemTouchHelperclasse qui simplifie le glissement pour rejeter et le glisser-déposer. Cela n'est peut-être pas aussi complet que certaines des bibliothèques, mais cela vient directement de l'équipe Android.

  • Mettez à jour votre build.gradle pour importer la version 22.2. + De la bibliothèque RecyclerView

    compile 'com.android.support:recyclerview-v7:22.2.+'
  • Instanciez un ItemTouchHelper avec un SimpleCallback approprié

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

    ** Notez que le SimpleCallback prend dans les directions que vous souhaitez activer le glisser-déposer et les directions que vous souhaitez activer le glissement.

  • Joindre à votre RecyclerView

    itemTouchHelper.attachToRecyclerView(recyclerView);
jmcdale
la source
7
Comment peut-on obtenir l'index de l'article glissé?
MaTTo
37
@Orochi En appelant getAdapterPosition () sur le viewHolder.
SqueezyMo
1
Ils n'ont manifestement pas trop réfléchi à la conception de ce composant. Cela ne fonctionne qu'avec un RecyclerView. Glisser pour ignorer existe pour des choses comme les barres-collations. Un composant plus générique qui pourrait être utilisé avec n'importe quel point de vue aurait été plus apprécié.
AndroidDev
4
Que faire si je souhaite gérer le cas lorsque l'utilisateur glisse partiellement, puis remet la vue en position? Apparemment, ce n'est pas possible (?) EDIT: ok, c'est possible, mais il y a une très petite marge dans laquelle vous pouvez rester avant que la vue ne soit balayée à la sortie. Toute suggestion?
Matteo
2
@Matteo: implémenter ItemTouchHelper.Callback et remplacer 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

Ici, dans Code, si l'utilisateur glisse vers la gauche, AlertDialog s'affiche et si l'utilisateur sélectionne SUPPRIMER, l'élément est supprimé de la base de données et la vue de recyclage est actualisée et si l'utilisateur sélectionne ANNULER, la vue de recyclage est telle qu'elle est.

Khyati Fatania
la source
fonctionne bien .. belle réponse.
Sagar Chavada
Impressionnant! Si facile à mettre en œuvre
dianakarenms
1
Vous n'avez pas vraiment besoin de la vérification if (direction == ItemTouchHelper.LEFT) // if swipe leftde la direction car elle ItemTouchHelper.SimpleCallbackest limitée à cette direction de balayage. Si vous voulez des balayages vers la gauche et vers la droite, ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)vous devez vérifier la direction.
Jacko
1
J'ai trouvé que cliquer en dehors de AlertDialog annulait la boîte de dialogue mais ne remettait pas l'élément que j'avais balayé. Vous pouvez capturer cela en ajoutant un OnCancelListener au 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 Fonctionne bien. J'ai trouvé adapter.notifyItemChanged(position);ramené l'article glissé, plutôt que notifyItemRemoved- ce qui est plus logique à mon humble avis.
winwaed le
14

peut-être que vous pourriez essayer cette bibliothèque:

https://github.com/daimajia/AndroidSwipeLayout

Mise à jour: je viens de trouver une autre bonne bibliothèque que vous pouvez utiliser avec RecyclerView:

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

Pierpaolo Paolini
la source
J'ai fait ma propre implémentation similaire à github.com/krossovochkin/Android-SwipeToDismiss-RecyclerView . La seule exigence était d'afficher Toast avec le bouton "Annuler", ce qui n'est pas couvert dans votre bibliothèque.
Viktor Yakunin
1
La bibliothèque de Daimajia ne prend pas en charge la fonction de balayage pour rejeter.
akohout
@raveN je viens de mettre à jour ma réponse.
Pierpaolo Paolini
2

Cette bibliothèque peut être utile.Vous pouvez implémenter undoen cours d' OnDissmissutilisationsupertoast

xcodebuild
la source
Hé, je vais essayer! Est-ce basé sur celui auquel Pierpaolo a répondu?
Garçon
C'est juste une OnTouchListener inspiration par ceci
xcodebuild
2

J'ai écrit la bibliothèque SwipeToDeleteRV qui prend en charge la fonction de balayage pour supprimer-annuler sur les vues de recycleur. Il est basé sur ItemTouchHelper et très facile à utiliser.

J'espère que cela peut être utile pour quelqu'un confronté aux mêmes problèmes.

À titre d'exemple, vous pouvez définir votre vue recycleur dans une mise en page XML comme normale, ainsi que certains attributs facultatifs:

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

Tous les attributs stdrv sont facultatifs. Si vous ne les spécifiez pas, les valeurs par défaut seront utilisées.

Créez ensuite un adaptateur qui sous-classe STDAdapter, assurez-vous d'appeler le constructeur de super classe. Quelque chose comme ça:

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

}

Assurez-vous ensuite de passer un appel à la setupSwipeToDeleteméthode pour configurer la fonction de balayage pour supprimer.

mRecyclerView.setupSwipeToDelete(your_adapter_instance, swipe_directions);

swipe_directions est la direction dans laquelle vous autorisez le balayage des éléments.

Exemple:

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

C'est tout! Pour des paramètres plus avancés (c.-à-d. Définir différents messages de suppression pour différents éléments, supprimer temporairement et définitivement des éléments, ...), veuillez consulter la page Lisez-moi du projet.

H. Nguyen
la source