Moving and swiping with RecyclerView
It's been a long time RecylcerView
is around. Most devs are already familiar with the basics of this useful class. We know how to create Adapters
, ViewHolders
, adding and removing items. But what about a bit more advanced things such as swiping items and moving items (drag-and-drop) inside the list?
The good news is that RecyclerView
makes these "advanced" things quite easy. The bad news is that it's a bit confusing to figure it out in the docs. My aim here is, now that I did figure it out, to put it all together hoping that I will save some time for the next developer looking how to do it.
Requirements
I assume that you already have your RecyclerView
set up and an Adapter
that handles the managing of your data. Pretty much, you have your list visible and functional (follow this guide to set up your list).
The SimpleCallback
This is where you define what events you want to react to (e.g. swiping and/or drag-and-drop) and what you want to do when these events happen.
class MyAdapter : RecyclerView.Adapter<ViewHolder>() {
private var tasks: List<Task> = arrayListOf()
[...]
private val simpleItemTouchCallback =
object : ItemTouchHelper.SimpleCallback(
// [1] The allowed directions for moving (drag-and-drop) items
UP or DOWN or START or END,
// [2] The allowed directions for swiping items
0) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder): Boolean {
// [3] Do something when an item is moved
val adapter = recyclerView.adapter
val from = viewHolder.adapterPosition
val to = target.adapterPosition
// [4] Keep up-to-date the underlying data set
Collections.swap(tasks, from, to)
// [5] Tell the adapter to switch the 2 items
adapter?.notifyItemMoved(from, to)
return true
}
override fun onSwiped(
viewHolder: RecyclerView.ViewHolder,
direction: Int) {
// [6] Do something when an item is swiped
}
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder);
// [7] Do something when the interaction with an item
// is complete
}
}
This SimpleCallback
is an abstract class and you need an object
to extend it. In its constructor, you define which directions you are allowing items to move (in [1]
) or swipe (in [2]
).
Then, there are dedicated methods that are called when an item is moved ([3]
) or swiped ([6]
). Notice that the switching of the items in the underlying list, is your responsibility ([4]
) and for the default item switching animation to happen, you need to let the adapter know about the move ([5]
).
Notice that in the case of moving items in the list, the method is called as soon as an item switches position with another one. This means that if you have a list with 5 items, and you move the last item to the first position, this method will be called 5 times while you drag your item to the top.
If you want to make an operation after the drop has happened (e.g. the entire move item interaction is completed and you need to save the new order of your underlying model to storage), you need to do it in the clearView
method ([7]
).
The attaching
This is the easy part. After you define what will happen in the events you are interested in, you just need to wrap it in an ItemTouchHelper
and attach it to your RecyclerView
.
ItemTouchHelper(simpleItemTouchCallback).attachToRecyclerView(recyclerView)
Happy moving and swiping items around in your RecyclerViews!