1

I am attempting to write a recyclerview which has some of the Viewholders inside it as stacked ontop of one another. The idea is that you can drag the topmost view above the stacked list and have drop it above where it becomes separate.

I managed to get this working using a Recyclerview with a custom RecyclerView.ItemDecoration. However, after I drop the item, i have the adapter call notifyDataSetChange to update the background code. This causes the the next item in the stack to appear to be the wrong one (though this does change sometimes if you touch the item and start scrolling, then it displays the correct one).
The custom RecyclerView.ItemDecoration class:

override fun getItemOffsets(
    outRect: Rect,
    view: View,
    parent: RecyclerView,
    state: RecyclerView.State
)
{
    val itemPosition = parent.getChildAdapterPosition(view)
    val adapter = parent.adapter
    if (adapter is BaseRecVAdapter)
    {
        val item = adapter.getDataModel(itemPosition)
        if (item is DragDropModel && item.mStackedPos != PMConsts.negNum)
        {
            if (item.mStackedPos != 0)
            {
                val context = view.context
                val top = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 148f, context.resources.displayMetrics).toInt()
                outRect.set(0, -top, 0, 0)
                return
            }
        }
    }
    super.getItemOffsets(outRect, view, parent, state)
}

The drag interface I made for the Adapter and the ItemTouchHelper.Callback can be found below:
interface ItemTouchHelperListener 
{
    fun onItemMove(fromPosition: Int, toPosition: Int): Boolean
    fun onClearView(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?)
}

The onItem move code is as follows:
override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean
    {
        var newToPosition = toPosition
        if (toPosition <= mDragUpLimit)
        {//Prevent items from being dragged above maximum movement.
            newToPosition = mDragUpLimit + 1
        }
        else if (toPosition >= mDragDownLimit)
        {//Cannot drag below stacked List...
            newToPosition = mDragDownLimit - 1
        }
        if (fromPosition < newToPosition)
            {
                for (i in fromPosition until newToPosition)
                {
                    swap(mDataList, i, i + 1)
                }
            }
            else
            {
                for (i in fromPosition downTo newToPosition + 1)
                {
                    swap(mDataList, i, i - 1)
                }
            }
            notifyItemMoved(fromPosition, newToPosition)
        return true
    }

I have a simple viewholder which is an invisible bar which i mark as the position you need to drag above in order to make a valid change to the list order.

I have the code call notifyDataSetChanged after the onClearView() method is called as I need to update the background features so that the next item in the stack is draggable and the background data feeding into the adapter is also updated. It seems the simplest way to keep the data updating smoothly, but I wonder if it is causing my problems

If someone would be able to give me a hand with this, I would be most grateful. I am tearing my hair out somewhat. I thought I had a good system setup but it was not quite working. I hope that this is enough information to get some help with this issue.
Thank you in advance

Sjkato83
  • 11
  • 2

0 Answers0