提问人:Dmitrii Volkov 提问时间:11/15/2023 最后编辑:Dmitrii Volkov 更新时间:11/15/2023 访问量:33
需要实现将项目从一个 recyclerview 拖放到另一个 recyclerview。Android, kotlin
Need to implement drag and drop of an item from one recyclerview to another recyclerview. Android, kotlin
问:
我在通过 ItemTouchHelper 实现时遇到了问题,然后我在 stackover 中发现,这是在两个 RecyclerView 之间拖放的解决方案 在 kotlin 上重写了它以进行测试,以弄清楚如何在我的应用程序中执行 - 这是我的 github - https://github.com/Avdors/RecyclerDragAndDrop 这是 Java 原版,已有 6 年历史 - https://github.com/jkozh/DragDropTwoRecyclerViews但是不能解决问题,拖放有效,但前提是我将一个项目从顶部拖到另一个项目。如果我拖动到空白区域或空的回收器视图中,则它不起作用,我希望将该项目移动到列表的末尾。谁能告诉我如何解决这个问题?
我试着看看其他 DragEvent,DragEvent.ACTION_DRAG_EXITED在释放一个项目时起作用,但它在释放和拖动一个对象时起作用,连续 4 次。如果你没有把一个元素放在另一个元素之上ACTION_DROP不起作用,请在项目中 Log 查看它从哪里开始。我认为可以用看不见的元素填充回收机,但似乎应该有一个更简单的解决方案。以下是基本实现的代码:'class DragListener(private val listener: Listener) : View.OnDragListener {
private var isDropped = false
override fun onDrag(v: View, event: DragEvent): Boolean {
when (event.action) {
// DragEvent.ACTION_DROP,
// DragEvent.ACTION_DRAG_EXITED
DragEvent.ACTION_DROP -> {
Log.d("MyLog", "ACTION_DROP")
isDropped = true
var positionTarget: Int
val viewSource = event.localState as? View
val viewId = v.id
val flItem = R.id.frame_layout_item
val tvEmptyListTop = R.id.tvEmptyListTop
val tvEmptyListBottom = R.id.tvEmptyListBottom
val rvTop = R.id.rvTop
val rvBottom = R.id.rvBottom
Log.d("MyLog", "viewId $viewId")
when (viewId) {
flItem, tvEmptyListTop, tvEmptyListBottom, rvTop, rvBottom -> {
Log.d("MyLog", "flItem, tvEmptyListTop, tvEmptyListBottom, rvTop, rvBottom")
val target: RecyclerView = when (viewId) {
tvEmptyListTop, rvTop -> v.rootView.findViewById(rvTop)
tvEmptyListBottom, rvBottom -> v.rootView.findViewById(rvBottom)
else -> v.parent as RecyclerView
}
positionTarget = v.tag as Int
Log.d("MyLog", "positionTarget = $positionTarget")
Log.d("MyLog", "viewSource $viewSource")
if (viewSource != null) {
val source = viewSource.parent as RecyclerView
val adapterSource = source.adapter as ListAdapter
val positionSource = viewSource.tag as Int
Log.d("MyLog", "positionSource $positionSource")
val list = adapterSource.getList()[positionSource]
val listSource = adapterSource.getList().toMutableList()
listSource.removeAt(positionSource)
adapterSource.updateList(listSource)
adapterSource.notifyDataSetChanged()
val adapterTarget = target.adapter as ListAdapter
Log.d("MyLog", "target $target")
val customListTarget = adapterTarget.getList().toMutableList()
Log.d("MyLog", "customListTarget $customListTarget")
if (positionTarget < 0) {
customListTarget.add(list)
// customListTarget.add(positionTarget, list)
} else {
customListTarget.add(positionTarget, list)
}
adapterTarget?.updateList(customListTarget)
adapterTarget?.notifyDataSetChanged()
}
}
}
}
DragEvent.ACTION_DRAG_EXITED -> {
Log.d("MyLog", "Enter ACTION_DRAG_EXITED")
}
}
if (!isDropped && event.localState != null) {
(event.localState as? View)?.visibility = View.VISIBLE
}
return true
}
}`
答:
一切都解决了,我需要为 recyclerview 放置侦听器。否则,在另一个 RecyclerView 上释放元素时,DragEvent.ACTION_DROP不起作用。我已经更新了 Github 中的代码,也许有人需要 kotlin 中更新的工作示例。https://github.com/Avdors/RecyclerDragAndDrop在我的活动中,我补充说:
tvEmptyListTop.setOnDragListListener(topListAdapter.getDragInstance())
rvTop.setOnDragListListener(topListAdapter.getDragInstance()).
和
tvEmptyListBottom.setOnDragListListListener(bottomListAdapter.getDragInstance())
rvBottom.setOnDragListListener(bottomListAdapter.getDragInstance())
以下是所有 MainActivity:
class MainActivity : AppCompatActivity(), Listener {
private lateinit var rvTop: RecyclerView
private lateinit var rvBottom: RecyclerView
private lateinit var tvEmptyListTop: TextView
private lateinit var tvEmptyListBottom: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
rvTop = findViewById(R.id.rvTop)
rvBottom = findViewById(R.id.rvBottom)
tvEmptyListTop = findViewById(R.id.tvEmptyListTop)
tvEmptyListBottom = findViewById(R.id.tvEmptyListBottom)
initTopRecyclerView()
initBottomRecyclerView()
tvEmptyListTop.visibility = View.GONE
tvEmptyListBottom.visibility = View.GONE
}
override fun setEmptyListTop(visibility: Boolean) {
tvEmptyListTop.visibility = if (visibility) View.VISIBLE else View.GONE
}
override fun setEmptyListBottom(visibility: Boolean) {
tvEmptyListBottom.visibility = if (visibility) View.VISIBLE else View.GONE
}
private fun initTopRecyclerView() {
rvTop.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
val topList = listOf("A", "B")
val topListAdapter = ListAdapter(topList, this)
rvTop.adapter = topListAdapter
tvEmptyListTop.setOnDragListener(topListAdapter.getDragInstance())
rvTop.setOnDragListener(topListAdapter.getDragInstance())
}
private fun initBottomRecyclerView() {
rvBottom.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
val bottomList = listOf("C", "D")
val bottomListAdapter = ListAdapter(bottomList, this)
rvBottom.adapter = bottomListAdapter
tvEmptyListBottom.setOnDragListener(bottomListAdapter.getDragInstance())
rvBottom.setOnDragListener(bottomListAdapter.getDragInstance())
}
}
评论