使用 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",但在这种情况下,您无法获得下方物品的位置(只是碰撞的事实)。这就是房车只显示数据,限制你行动的情况。
另一种解决方案 - 创建不同的列表并通过位置更改替换项目,然后更新数据库。
无论如何,这些只是示例。
在我的例子中,我放弃了上面的方法,因为那是多余的,并且只使用了交集检查。
因此,选择不仅不会使您的代码复杂化,而且会使其更合适和更实用的方法。
在我的项目中,我有一个回收器视图,用于两种情况(实体的两种状态)。我想让项目在两个 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",但在这种情况下,您无法获得下方物品的位置(只是碰撞的事实)。这就是房车只显示数据,限制你行动的情况。
另一种解决方案 - 创建不同的列表并通过位置更改替换项目,然后更新数据库。
无论如何,这些只是示例。
在我的例子中,我放弃了上面的方法,因为那是多余的,并且只使用了交集检查。
因此,选择不仅不会使您的代码复杂化,而且会使其更合适和更实用的方法。