Android - Drag and Drop on ConcatAdapter

768 Views Asked by At

I'm trying to implement a drag and drop in a ConcatAdapter. I did a ConcatAdapter bc I have multiples sections where the items are different, so I just need to drag and drop inside one section.

I did a ConcatAdapter with 2 adapters I did the ItemTouchHelper for the recycler view -> itemTouchHelper.attachToRecyclerView(binding.recyclerView)

I guess that it's something related with the ItemTouchHelper bc its set on the RecyclerView and not on the adapter.

Is there any way I can set just the drag and drop for 1 adapter inside the ConcatAdapter?

1

There are 1 best solutions below

0
Reza Mohammadi On

Inside onMove from ItemTouchHelper.Callback, you can just decide to ignore some of the moves. Use viewHolder (the ViewHolder which is being dragged) and targetViewHolder and check their bindingAdapter. Or if they're instances of the same adapter, you can use a field that has been set on adapter initialization, to determine which adapter they are.

In the example below I have two adapters, both of type TaskAdapter, but second one holds completed tasks. Uncompleted tasks can't be moved between completed ones and completed tasks can't be moved at all. So if targetViewHolder is bound by the adapter flagged as completed, I just return false and ignore the move. Obviously an item has been dragged over that target item but since it's not actually moving, user understands this isn't allowed and will give up. I think it's acceptable and better than having multiple RecyclerViews.

override fun onMove(
    recyclerView: RecyclerView,
    viewHolder: RecyclerView.ViewHolder,
    targetViewHolder: RecyclerView.ViewHolder
): Boolean {
    val targetAdapter = targetViewHolder.bindingAdapter as TaskAdapter
    if (targetAdapter.completed) return false
    val adapter = viewHolder.bindingAdapter as TaskAdapter
    adapter.moveItem(
        viewHolder.bindingAdapterPosition,
        targetViewHolder.bindingAdapterPosition
    )
    return true
}

If you want some items can't be dragged in the first place, you can just return 0 from getDragDirs. In this example they are completed tasks.

override fun getDragDirs(
    recyclerView: RecyclerView,
    viewHolder: RecyclerView.ViewHolder
): Int {
    val adapter = viewHolder.bindingAdapter as TaskAdapter
    if (adapter.completed) return 0
    return super.getDragDirs(recyclerView, viewHolder)
}