Android Recycleview dragging items within a nested recyclerview for the second time is not working properly

44 Views Asked by At

I attempted to integrate the dragging feature for both the primary item and the extended list within that list.

It functioned OK, however when I closed and reopened an item, the item (in extended list) stopped moving with the cursor.

Check out this video to understand the issue. video link

Adapter code.

class ItemAdapter(private val items: MutableList<ItemModel>) :
RecyclerView.Adapter<ItemAdapter.ViewHolder>() {

private var expandedItemPosition: Int = -1

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val inflater = LayoutInflater.from(parent.context)
    val binding: ItemListBinding =
        DataBindingUtil.inflate(inflater, R.layout.item_list, parent, false)
    return ViewHolder(binding)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(items[position])
}

override fun getItemCount(): Int {
    return items.size
}

fun onItemMove(fromPosition: Int, toPosition: Int) {
    if (fromPosition < toPosition) {
        for (i in fromPosition until toPosition) {
            items[i] = items.set(i + 1, items[i])
        }
    } else {
        for (i in fromPosition downTo toPosition + 1) {
            items[i] = items.set(i - 1, items[i])
        }
    }
    notifyItemMoved(fromPosition, toPosition)
}

inner class ViewHolder(private val binding: ItemListBinding) :
    RecyclerView.ViewHolder(binding.root) {

    init {
        binding.root.setOnClickListener {
            val position = adapterPosition
            expandedItemPosition = if (position == expandedItemPosition) {
                -1 // Collapse the currently expanded item
            } else {
                position // Expand the clicked item
            }
            notifyDataSetChanged() // Notify the adapter of the item changes
        }
    }

    fun bind(item: ItemModel) {
        binding.viewModel = item
        val isExpanded = adapterPosition == expandedItemPosition
        binding.isExpanded = isExpanded
        binding.executePendingBindings()

        if (isExpanded) {
            val expandedRecyclerView = binding.expandedRecyclerView
            expandedRecyclerView.adapter = ExpandedItemAdapter(item.expandedList)

            val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
                ItemTouchHelper.UP or ItemTouchHelper.DOWN,
                0
            ) {
                override fun onMove(
                    recyclerView: RecyclerView,
                    viewHolder: RecyclerView.ViewHolder,
                    target: RecyclerView.ViewHolder
                ): Boolean {
                    val fromPosition = viewHolder.adapterPosition
                    val toPosition = target.adapterPosition
                    (expandedRecyclerView.adapter as ExpandedItemAdapter).onItemMove(
                        fromPosition,
                        toPosition
                    )
                    return true
                }

                override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                    Log.d("CheckingSwiped", "onSwiped: $adapterPosition")
                }

                override fun onMoved(
                    recyclerView: RecyclerView,
                    viewHolder: RecyclerView.ViewHolder,
                    fromPos: Int,
                    target: RecyclerView.ViewHolder,
                    toPos: Int,
                    x: Int,
                    y: Int
                ) {
                    Log.d("CheckingSwiped", "onMoved: $fromPos ::: $toPos")

                    super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
                }

                override fun isLongPressDragEnabled(): Boolean {
                    return true
                }
            })

            itemTouchHelper.attachToRecyclerView(expandedRecyclerView)
        } else {
            binding.expandedRecyclerView.adapter = null
        }
    }
}

}

If you identify any errors in my code, please let me know and give a solution. Thx!

1

There are 1 best solutions below

2
Jackey kabra On

Check the below code may be it helpful

class ItemAdapter(private val items: MutableList<ItemModel>) :
RecyclerView.Adapter<ItemAdapter.ViewHolder>() {

private var expandedItemPosition: Int = -1
private var itemTouchHelper: ItemTouchHelper? = null

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val inflater = LayoutInflater.from(parent.context)
    val binding: ItemListBinding =
        DataBindingUtil.inflate(inflater, R.layout.item_list, parent, false)
    return ViewHolder(binding)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(items[position])
}

override fun getItemCount(): Int {
    return items.size
}

fun onItemMove(fromPosition: Int, toPosition: Int) {
    if (fromPosition < toPosition) {
        for (i in fromPosition until toPosition) {
            items[i] = items.set(i + 1, items[i])
        }
    } else {
        for (i in fromPosition downTo toPosition + 1) {
            items[i] = items.set(i - 1, items[i])
        }
    }
    notifyItemMoved(fromPosition, toPosition)
}

inner class ViewHolder(private val binding: ItemListBinding) :
    RecyclerView.ViewHolder(binding.root) {

    init {
        binding.root.setOnClickListener {
            val position = adapterPosition
            expandedItemPosition = if (position == expandedItemPosition) {
                -1 // Collapse the currently expanded item
            } else {
                position // Expand the clicked item
            }
            notifyDataSetChanged() // Notify the adapter of the item changes
        }
    }

    fun bind(item: ItemModel) {
        binding.viewModel = item
        val isExpanded = adapterPosition == expandedItemPosition
        binding.isExpanded = isExpanded
        binding.executePendingBindings()

        val expandedRecyclerView = binding.expandedRecyclerView
        if (isExpanded) {
            expandedRecyclerView.adapter = ExpandedItemAdapter(item.expandedList)
        } else {
            expandedRecyclerView.adapter = null
        }

        if (itemTouchHelper == null) {
            itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
                ItemTouchHelper.UP or ItemTouchHelper.DOWN,
                0
            ) {
                override fun onMove(
                    recyclerView: RecyclerView,
                    viewHolder: RecyclerView.ViewHolder,
                    target: RecyclerView.ViewHolder
                ): Boolean {
                    val fromPosition = viewHolder.adapterPosition
                    val toPosition = target.adapterPosition
                    (expandedRecyclerView.adapter as? ExpandedItemAdapter)?.onItemMove(
                        fromPosition,
                        toPosition
                    )
                    return true
                }

                override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                    Log.d("CheckingSwiped", "onSwiped: $adapterPosition")
                }

                override fun onMoved(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder,
                fromPos: Int,
                target: RecyclerView.ViewHolder,
                toPos: Int,
                x: Int,
                y: Int
            ) {
                Log.d("CheckingSwiped", "onMoved: $fromPos ::: $toPos")

                super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
            }

            override fun isLongPressDragEnabled(): Boolean {
                return true
            }
        })

        itemTouchHelper.attachToRecyclerView(expandedRecyclerView)
    } else {
        binding.expandedRecyclerView.adapter = null
    }
}
}

}