Using ItemTouchHelper class we can DRAG, DROP, & SWIPE items in the recycler view; but how to just merge two items when dragged & dropped on one another?
Is it possible to do using ItemTouchHelper (or) is there any other API for that?
You could override onMove()
in your ItemTouchHelper
, it is called when you drag item A over item B. It gets called with the parameters viewHolder: RecyclerView.ViewHolder
and target: RecyclerView.ViewHolder
where viewHolder
is the viewHolder of item A, and target
is item B.
Have some variable of type ViewHolder, that you set to target in onMove, to always have a reference to the item below item A.
override clearView()
to detect when the item is dropped, update your model in the background, so itemA now is merged with target, then call notifyItemChanged(itemA.adapterPosition)
and notifyItemRemoved(itemB.adapterPosition)
to animate a "merge"
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>