skip to Main Content

I have a recycler view, its list is stored in firestore. I want to allow user to reorder the items using drag and drop. When the user removes the hold (drops the item) I want to call the function to update the firestore but whenever the position is changed even while dragging to the desired position the function is getting called. How can I call the function only when the item is placed.

val itemTouchHelper = ItemTouchHelper(
        object: ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0){
            override fun onMove(
                recyclerView: RecyclerView,
                source: RecyclerView.ViewHolder,
                target: RecyclerView.ViewHolder
            ): Boolean {
                val sourcePosition = source.adapterPosition
                val targetPosition = target.adapterPosition

                Collections.swap(itemList, sourcePosition, targetPosition)
                adapter.notifyItemMoved(sourcePosition, targetPosition)

// Firestore update
                updateFirestoreList()

                return true
            }

            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                TODO("Not yet implemented")
            }
        })

2

Answers


  1. The way that I achieved it was by overriding the clearView() method of ItemTouchHelper, and calling a callback from it. It would be something like below:

    class MyTouchHelper(val onActionEnded: () -> Unit) : ItemTouchHelper.SimpleCallback(UP or DOWN, 0) {
    
        override fun onMove(
            recyclerView: RecyclerView,
            viewHolder: RecyclerView.ViewHolder,
            target: RecyclerView.ViewHolder,
        ): Boolean {
            recyclerView.adapter?.let { adapter ->
                adapter as MyListAdapter
                val from = viewHolder.absoluteAdapterPosition
                val to = target.absoluteAdapterPosition
                adapter.onItemMoved(from, to)
                return true
            }
            return false
        }
    
        override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
    
        override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
            super.clearView(recyclerView, viewHolder)
            onActionEnded()
        }
    }
    

    The onItemMovied(from, to), is a function in the MyListAdapter class that is having an implementation like the below:

    fun onItemMoved(from: Int, to: Int) {
        val list = currentList.toMutableList()
        list.add(to, list.removeAt(from))
        submitList(list)
    }
    

    It just updates the list with the new item’s position(you might have a different approach, feel free to use it according to your need or not to use it at all).

    And finally, where you are attaching the MyTouchHelper, you can use its callback to call your specific function like below:

    ItemTouchHelper(MyTouchHelper {
        updateFirestoreList()// Or any other functions that you want.
    }).attachToRecyclerView(recyclerView)
    

    I hope it helps.

    Login or Signup to reply.
  2. When you selected to drag, store this position

    var sourcePosition = -1
    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
         super.onSelectedChanged(viewHolder, actionState)
         if(actionState != ItemTouchHelper.ACTION_STATE_IDLE){
               sourcePosition = viewHolder!!.adapterPosition
         }
    }
    

    When you drop clearView will be called, get position of ViewHolder and swap Collection

    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        super.clearView(recyclerView, viewHolder)
        val targetPosition = viewHolder.adapterPosition
        if(sourcePosition != -1 && sourcePosition != targetPosition){
            Collections.swap(itemList, sourcePosition, targetPosition)
        }
        sourcePosition = -1
    }
    

    I hope it helps :))

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search