使用 ViewModel 在两个 RV 适配器之间创建拖放并更改数据

Create drag and drop between two RV adapters with data changing using ViewModel

在我的项目中,我有一个回收器视图,用于两种情况(实体的两种状态)。我想让项目在两个 RV 之间可拖动,但是 DragEvent.ACTION_DROP 更改了位于项目下方的元素的状态。有可能逆转吗?我能得到物品掉落完成的位置吗?我找到了许多其他解决方案,但就我而言,最大的问题是更改项目的位置,因为它们是通过主片段中 ViewModel 的方法调用进行更新的。 也许我需要选择另一种数据显示和创建方式,例如,具有单独列表的不同适配器?

itemView.setOnTouchListener 初始化块中的代码:

    override fun onItemLongTap() {

                    itemView.tag = adapterPosition

                    val shadowBuilder = MyDragShadowBuilder(itemView)
                    val item = ClipData.Item(itemView.tag as? CharSequence)
                    val data = ClipData(
                        itemView.tag as? CharSequence,
                        arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN),
                        item
                    )
                    itemView.startDrag(data, shadowBuilder, itemView, 0)
                }
            })

            val customDrag = View.OnDragListener { view, event ->
                if (event.action == DragEvent.ACTION_DROP) {
                    onItemDrag?.invoke(items!![adapterPosition])

                }
                true
            }

            itemView.setOnDragListener(customDrag)

使用 var onItemDrag 在主片段中调用:((Item) -> Unit)? = 空:

        firstAdapter?.onItemDrag = {
            itemViewModel.changeFirstState(it.id)
        }

        secondAdapter?.onItemDrag = {
            itemViewModel.changeSecondState(it.id)
        }

我差点忘了回答我自己的问题,但我想有人可能有类似的问题,所以看看。

如果你想使用唯一的一个列表并通过数据库请求更新项目的状态,你可以在与另一个视图(使用 Rect())相交时用 lambda 处理 "ACTION_DRAG_EXITED",但在这种情况下,您无法获得下方物品的位置(只是碰撞的事实)。这就是房车只显示数据,限制你行动的情况。

另一种解决方案 - 创建不同的列表并通过位置更改替换项目,然后更新数据库。

无论如何,这些只是示例。

在我的例子中,我放弃了上面的方法,因为那是多余的,并且只使用了交集检查。

因此,选择不仅不会使您的代码复杂化,而且会使其更合适和更实用的方法。