
Il existe de nombreux didacticiels, bibliothèques et implémentations de glisser- déposer et de glisser- déplacer pour supprimer dans Android à l'aide de RecyclerView. La plupart d'entre eux utilisent toujours le View.OnDragListener déconseillé et l'approche SwipeToDismiss développée par Roman Nurik. Bien que de nouvelles méthodes plus efficaces soient déjà disponibles. Très peu utilisent les dernières API, s'appuyant souvent sur GestureDetectors
et onInterceptTouchEvent
ou d'autres implémentations plus complexes. En fait, il existe un moyen très simple d'ajouter ces fonctions à RecyclerView
. Cela ne nécessite qu'une seule classe, qui fait également partie de la bibliothèque de support Android.
ItemTouchHelper
ItemTouchHelper est un utilitaire puissant qui s'occupe de tout ce que vous devez faire pour ajouter des fonctions de glisser-déposer et de glisser- déplacer pour RecyclerView
. Cet utilitaire est une sous-classe de RecyclerView.ItemDecoration , ce qui facilite son ajout à presque tous les LayoutManager
et adaptateurs existants. Il fonctionne également avec l'animation d'élément et offre la possibilité de glisser-déposer des éléments d'un type vers un autre endroit de la liste et bien plus encore. Dans cet article, je vais démontrer une implémentation simple de ItemTouchHelper
. Plus tard, dans le cadre de cette série d'articles, nous élargirons la portée et envisagerons d'autres options.
Remarque Vous voulez voir le résultat tout de suite? Découvrez Github: Android-ItemTouchHelper-Demo . Le premier commit concerne cet article. Le fichier de démonstration .apk
peut être téléchargé ici .

Personnalisation
Nous devons d'abord configurer le RecyclerView
. Si ce n'est pas déjà fait, ajoutez la dépendance RecyclerView
à votre fichier build.gradle
.
compile 'com.android.support:recyclerview-v7:22.2.0'
ItemTouchHelper
fonctionnera avec presque tous les RecyclerView.Adapter
et LayoutManager
, mais cet article est basé sur des exemples utilisant ces fichiers .
Utilisation de ItemTouchHelper et ItemTouchHelper.Callback
Pour utiliser ItemTouchHelper
, vous devez créer un ItemTouchHelper.Callback . Il s'agit d'une interface qui vous permet de suivre les actions de mouvement ( eng. Move) et de glisser ( eng. Swipe). De plus, vous pouvez contrôler ici l'état du composant de view
sélectionné et remplacer l'animation par défaut. Il existe une classe d'assistance que vous pouvez utiliser si vous souhaitez utiliser l'implémentation de base, SimpleCallback . Mais pour comprendre comment cela fonctionne dans la pratique, nous ferons tout par nous-mêmes.
Les principales fonctions de l'interface que nous devons redéfinir pour inclure les fonctionnalités de base du glisser-déposer et du glisser- déplacer :
getMovementFlags(RecyclerView, ViewHolder) onMove(RecyclerView, ViewHolder, ViewHolder) onSwiped(ViewHolder, int)
Nous utiliserons également plusieurs méthodes d'assistance:
isLongPressDragEnabled() isItemViewSwipeEnabled()
Examinons-les un par un.
@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); }
ItemTouchHelper
facilite la détermination de la direction d'un événement. Vous devez remplacer la méthode getMovementFlags()
pour indiquer les directions de glisser-déposer qui seront prises en charge. Pour créer des indicateurs de retour, utilisez la méthode d'assistance ItemTouchHelper.makeMovementFlags(int, int)
. Dans cet exemple, nous autorisons le glisser-déposer dans les deux sens.
@Override public boolean isLongPressDragEnabled() { return true; }
ItemTouchHelper
ne peut être utilisé que par glisser-déposer sans fonctionnalité de balayage (ou vice versa), vous devez donc spécifier exactement quelles fonctionnalités doivent être prises en charge. La méthode isLongPressDragEnabled()
doit renvoyer true
pour prendre en charge le glisser-déposer après un long clic sur l'élément RecyclerView
. Vous pouvez également appeler la ItemTouchHelper.startDrag(RecyclerView.ViewHolder)
pour commencer à faire glisser manuellement. Nous considérerons cette option plus tard.
@Override public boolean isItemViewSwipeEnabled() { return true; }
Pour activer le fouet après avoir touché n'importe où dans le composant de view
, renvoyez simplement true
partir de la méthode isItemViewSwipeEnabled()
. Vous pouvez également appeler la ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)
pour démarrer le balayage manuellement.
Les deux méthodes suivantes, onMove()
et onSwiped()
, sont requises pour vous informer des mises à jour des données. Donc, nous allons d'abord créer une interface qui permettra à ces événements de passer le long de la chaîne d'appel.
ItemTouchHelperAdapter.java
public interface ItemTouchHelperAdapter { void onItemMove(int fromPosition, int toPosition); void onItemDismiss(int position); }
La façon la plus simple de procéder consiste à demander à RecyclerListAdapter d' implémenter l'écouteur.
public class RecyclerListAdapter extends RecyclerView.Adapter<ItemViewHolder> implements ItemTouchHelperAdapter {
Il est très important d'appeler les notifyItemRemoved()
et notifyItemMoved()
pour que l'adaptateur voit les modifications. Il convient également de noter que nous changeons la position de l'élément à chaque fois que la composante de view
est déplacée vers un nouvel index, et non pas à la toute fin du mouvement (l'événement «drop») .
Nous pouvons maintenant revenir à la création de SimpleItemTouchHelperCallback
, car nous devons toujours remplacer les onMove()
et onSwiped()
. Ajoutez d'abord le constructeur et le champ de l'adaptateur:
private final ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback( ItemTouchHelperAdapter adapter) { mAdapter = adapter; }
Redéfinissez ensuite les événements restants et signalez-les à l'adaptateur:
@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()); }
Par conséquent, la classe Callback
devrait ressembler à ceci:
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()); } }
Lorsque le rappel est prêt, nous pouvons créer un ItemTouchHelper
et appeler la attachToRecyclerView(RecyclerView)
(par exemple, dans MainFragment.java ):
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter); ItemTouchHelper touchHelper = new ItemTouchHelper(callback); touchHelper.attachToRecyclerView(recyclerView);
Après avoir commencé, vous devriez obtenir quelque chose comme ceci:

Conclusion
Il s'agit de l'implémentation la plus simplifiée de ItemTouchHelper
. Cependant, vous remarquerez peut-être que vous n'avez pas besoin d'utiliser une bibliothèque tierce pour implémenter les actions standard de glisser-déplacer et de glisser-rejeter dans RecyclerView
. Dans la partie suivante, nous porterons plus d'attention à l'apparence des éléments lors du glisser-déposer.
Code source
J'ai créé un projet sur GitHub pour démontrer ce qui est couvert dans cette série d'articles: Android-ItemTouchHelper-Demo . Le premier commit concerne principalement cette partie et un peu la seconde .
→ Faites glisser et faites glisser dans RecyclerView. Partie 2: glisser-déposer des contrôleurs, des grilles et des animations personnalisées