需要实现将项目从一个 recyclerview 拖放到另一个 recyclerview。Android, kotlin

Need to implement drag and drop of an item from one recyclerview to another recyclerview. Android, kotlin

提问人:Dmitrii Volkov 提问时间:11/15/2023 最后编辑:Dmitrii Volkov 更新时间:11/15/2023 访问量:33

问:

我在通过 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
}

}`

Kotlin Android-RecyclerView 拖放 拖拽事件

评论

0赞 Community 11/17/2023
请修剪您的代码,以便更轻松地找到您的问题。请遵循这些准则,以创建最小的可重现示例

答:

0赞 Dmitrii Volkov 11/15/2023 #1

一切都解决了,我需要为 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())
}

}