Drag and reorder RecyclerView items in a user friendly manner

What we want to do

Step 1: Implement ItemTouchHelper by the book

private val itemTouchHelper by lazy {  // 1. Note that I am specifying all 4 directions. 
// Specifying START and END also allows
// more organic dragging than just specifying UP and DOWN.
val simpleItemTouchCallback =
object : ItemTouchHelper.SimpleCallback(UP or
DOWN or
START or
END
, 0) {

override fun onMove(recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder): Boolean
{

val adapter = recyclerView.adapter as MainRecyclerViewAdapter
val from = viewHolder.adapterPosition
val to = target.adapterPosition
// 2. Update the backing model. Custom implementation in
// MainRecyclerViewAdapter. You need to implement
// reordering of the backing model inside the method.
adapter.moveItem(from, to)
// 3. Tell adapter to render the model update.
adapter.notifyItemMoved(from, to)

return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder,
direction: Int) {
// 4. Code block for horizontal swipe.
// ItemTouchHelper handles horizontal swipe as well, but
// it is not relevant with reordering. Ignoring here.
}
}
ItemTouchHelper(simpleItemTouchCallback)
}
override fun onCreate(savedInstanceState: Bundle?) {
...
itemTouchHelper.attachToRecyclerView(recyclerView)
}
Product of first step : by the book implementation of reorder action

Step 2 : Highlight the row while being selected.

private val itemTouchHelper by lazy {
val simpleItemTouchCallback =
object : ItemTouchHelper.SimpleCallback(UP or
DOWN or
START or
END, 0) {
// 1. This callback is called when a ViewHolder is selected.
// We highlight the ViewHolder here.
override fun onSelectedChanged(viewHolder: ViewHolder?,
actionState: Int)
{
super.onSelectedChanged(viewHolder, actionState)

if (actionState == ACTION_STATE_DRAG) {
viewHolder?.itemView?.alpha = 0.5f
}
}
// 2. This callback is called when the ViewHolder is
// unselected (dropped). We unhighlight the ViewHolder here.
override fun clearView(recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder)
{
super.clearView(recyclerView, viewHolder)
viewHolder?.itemView?.alpha = 1.0f
}
}
...}

Step 3 : Implement a handle as an indicator

fun startDragging(viewHolder: RecyclerView.ViewHolder) { 
itemTouchHelper.startDrag(viewHolder)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
MainRecyclerViewHolder {
...
// 1. Implement `OnTouchListener` on handleView
viewHolder.itemView.handleView.setOnTouchListener {
view, event ->
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
// 2. When we detect touch-down event, we call the
// startDragging(...) method we prepared above
activity.startDragging(viewHolder)
}
return@setOnTouchListener true
}
...
}

Summary

Coding in Swift, want to learn Flutter, a Dad, a Rock Climber, learning Parkour and Guitar