RecyclerView swipe to delete easier than you thought

As is often the case, sometimes you need to enhance the functionality in the application using 3rd party libraries.

Of course, there’s nothing wrong with it:

  • often such code has good quality,
  • you can save some time,
  • in general, reinventing the wheel is not a good idea.

There is also the other side of the coin:

  • open source is cool, but when you find a bug in the library, you need to fix it by yourself,
  • customisation might be cumbersome,
  • you have to accept library’s dependencies, even if you’re not using them,

Last but not least, in my opinion, using a ready-made solution prevents us from discovering and learning new stuff.

It was similar in my case. Ability to delete rows from RecyclerView’s list was all that I needed. A quick look at the documentation and I realised that can be accomplished very easily!

ItemTouchHelper.SimpleCallback

Using this class, we can detect and react to events related to:

  • swipe items (from right, left or both sides)
  • move items (up, down or both)

Let’s create our implementation based on SimpleCallback (to make code cleaner I placed only the most important fragments, check full code):

abstract class SwipeToDeleteCallback(context: Context) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {

override fun onMove(...): Boolean {
return false // We don't want support moving items up/down
}

// Let's draw our delete view
override fun onChildDraw(canvas, recyclerView, viewHolder, ..) {
val itemView = viewHolder.itemView
val itemHeight = itemView.bottom - itemView.top

// Draw the red delete background
background.color = backgroundColor
background.setBounds(
itemView.right + dX.toInt(),
itemView.top,
itemView.right,
itemView.bottom
)
background.draw(canvas)

// Calculate position of delete icon
val iconTop = itemView.top + (itemHeight - inHeight) / 2
val iconMargin = (itemHeight - inHeight) / 2
val iconLeft = itemView.right - iconMargin - inWidth
val iconRight = itemView.right - iconMargin
val iconBottom = iconTop + inHeight

// Draw the delete icon
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
icon.draw(canvas)

super.onChildDraw(canvas, recyclerView, viewHolder, ...)
}
}

SimpleCallback’s constructor is using two parameters — which directions we want to support, in our case just swipe from right to left. In onChildDraw method we need to manually calculate and draw background with icon (I used ic_delete from Material icons).

Next thing is to connect Callback with our RecyclerView:

recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView
.adapter = SimpleAdapter()

val swipeHandler = object : SwipeToDeleteCallback(context) {
override fun onSwiped(...) {
val adapter = recyclerView.adapter as SimpleAdapter
adapter.removeAt(viewHolder.adapterPosition)
}
}
val itemTouchHelper = ItemTouchHelper(swipeHandler)
itemTouchHelper.attachToRecyclerView(recyclerView)

Finally, the last thing is ability to delete item in adapter. We can achieve this by doing that:

class SimpleAdapter : RecyclerView.Adapter<SimpleAdapter.VH>() {

// ...

fun removeAt(position: Int) {
items.removeAt(position)
notifyItemRemoved(position)
}
}

That’s it! Thanks to this quick implementation you can add cool feature in your application.

Swipe to remove

Links: