在 ANDROID 中相互拖放时在 Recyclerview 中合并项目?

MERGE ITEMS in Recycler View when dragged & dropped on one another, in ANDROID?

使用 ItemTouchHelper class 我们可以在回收站视图中拖放、滑动项目;但是如何在相互拖放时合并两个项目?

是否可以使用 ItemTouchHelper(或)是否还有其他 API?

您可以覆盖 ItemTouchHelper 中的 onMove(),当您将项目 A 拖到项目 B 上时调用它。它使用参数 viewHolder: RecyclerView.ViewHoldertarget: RecyclerView.ViewHolder 调用其中 viewHolder 是项目 A 的 viewHolder,target 是项目 B。

有一些您在 onMove 中设置为目标的 ViewHolder 类型的变量,以始终引用项目 A 下的项目。

重写 clearView() 以检测物品何时掉落,在后台更新您的模型,因此 itemA 现在与目标合并,然后调用 notifyItemChanged(itemA.adapterPosition)notifyItemRemoved(itemB.adapterPosition) 为 a 设置动画“合并”

class MainActivity : AppCompatActivity() {

    companion object{
        val fruit = arrayListOf("apple", "pear", "orange", "banana", "grape", "pineapple")
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val recyclerView1 = findViewById<RecyclerView>(R.id.testRecycler)
        val layoutManager = LinearLayoutManager(this)
        recyclerView1.layoutManager = layoutManager

        val adapter = FruitAdapter()
        recyclerView1.adapter = adapter

        val itemTouchHelper = ItemTouchHelper(
            object : ItemTouchHelper.SimpleCallback(
                ItemTouchHelper.UP or ItemTouchHelper.DOWN,
                0
            ) {
                @SuppressLint("StaticFieldLeak")
                var target: RecyclerView.ViewHolder? = null
                @SuppressLint("StaticFieldLeak")
                var moving: RecyclerView.ViewHolder? = null
                override fun clearView(
                    recyclerView: RecyclerView,
                    viewHolder: RecyclerView.ViewHolder
                ) {
                    if(target!=null && moving != null){
                        val targetPos = target!!.adapterPosition
                        val sourcePos = moving!!.adapterPosition
                        fruit[targetPos] += "\n\n" + fruit[sourcePos]
                        fruit.removeAt(sourcePos)
                        target = null
                        moving = null
                        adapter.notifyDataSetChanged()
                    }
                }

                override fun onMove(
                    recyclerView: RecyclerView,
                    viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder
                ): Boolean {
                    this.target = target
                    this.moving = viewHolder
                    return true
                }

                override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                    TODO("Not yet implemented")
                }
            })

        itemTouchHelper.attachToRecyclerView(recyclerView1)
    }
}

class FruitAdapter: RecyclerView.Adapter<FruitAdapter.FruitViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {
        val itemView = LayoutInflater.from(parent.context)
            .inflate(R.layout.item, parent, false)
        return FruitViewHolder(itemView)
    }
    override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {
        holder.itemView.findViewById<TextView>(R.id.fruitNameTextView).text = MainActivity.fruit[position]
    }

    override fun getItemCount(): Int {
        return MainActivity.fruit.size
    }

    class FruitViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){}
}

item.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:padding="20px"
    android:layout_margin="20px"
    android:background="@color/teal_200"
    android:layout_height="wrap_content">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/fruitNameTextView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:id="@+id/testRecycler"
        android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>