Android & Kotlin

Drag and drop RecyclerView item Android

Pinterest LinkedIn Tumblr

Welcome to drag and drop RecyclerView item android example. In this tutorial, we’ll learn how to change the position of the recycler view items via drag and drop. For doing that, we will create a sample app that contains a recycler view with drag and drop functionality. Let’s get started.

Drag and Drop RecyclerView Item Demo App
1. Open android studio and create new project

Create a new android project with Kotlin and recycler view dependency inside app/build.gradle

implementation 'androidx.recyclerview:recyclerview:1.1.0'
2. Create RecyclerView Adapter

Now create a recycler view adapter named is DragDropRecyclerAdapter.

package com.dragdroprecyclerview

import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.layout_recyclerview_item.view.*
import java.util.*


class DragDropRecyclerAdapter(private val startDragListener: OnStartDragListener) :
    RecyclerView.Adapter<DragDropRecyclerAdapter.ItemViewHolder>(),
    ItemMoveCallbackListener.Listener {
    private var users = emptyList<String>().toMutableList()

    fun setUsers(newUsers: List<String>) {
        users.addAll(newUsers)
    }

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

    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val user = users[position]
        holder.bind(user)

        holder.itemView.imageView.setOnTouchListener { _, event ->
            if (event.action == MotionEvent.ACTION_DOWN) {
                this.startDragListener.onStartDrag(holder)
            }
            return@setOnTouchListener true
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        val itemView = LayoutInflater.from(parent.context)
            .inflate(R.layout.layout_recyclerview_item, parent, false)
        return ItemViewHolder(itemView)
    }

    class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(text: String) {
            itemView.textView.text = text

        }
    }

    override fun onRowMoved(fromPosition: Int, toPosition: Int) {
        if (fromPosition < toPosition) {
            for (i in fromPosition until toPosition) {
                Collections.swap(users, i, i + 1)
            }
        } else {
            for (i in fromPosition downTo toPosition + 1) {
                Collections.swap(users, i, i - 1)
            }
        }
        notifyItemMoved(fromPosition, toPosition)
    }

    override fun onRowSelected(itemViewHolder: ItemViewHolder) {

    }

    override fun onRowClear(itemViewHolder: ItemViewHolder) {

    }
}
3. Let’s create a layout file named is layout_recyclerview_item.xml and paste below code
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:background="#F7EEEE"
    android:layout_margin="8dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:textSize="18sp"

        app:fontFamily="sans-serif-medium"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/imageView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Drag and Drop Recycler View example" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_scroll" />
</androidx.constraintlayout.widget.ConstraintLayout>
4. Write an ItemMoveCallback listener class which extends ItemTouchHelper.Callback
package com.dragdroprecyclerview

import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView

class ItemMoveCallbackListener(val adapter: DragDropRecyclerAdapter) : ItemTouchHelper.Callback() {


    override fun getMovementFlags(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder
    ): Int {
        val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
        return makeMovementFlags(dragFlags, 0)
    }

    override fun isItemViewSwipeEnabled(): Boolean {
        return false
    }

    override fun isLongPressDragEnabled(): Boolean {
        return false
    }

    override fun onMove(
        recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        adapter.onRowMoved(viewHolder.adapterPosition, target.adapterPosition)
        return true
    }

    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            if (viewHolder is DragDropRecyclerAdapter.ItemViewHolder) {
                adapter.onRowSelected(viewHolder)
            }
        }
        super.onSelectedChanged(viewHolder, actionState)
    }

    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        super.clearView(recyclerView, viewHolder)
        if (viewHolder is DragDropRecyclerAdapter.ItemViewHolder) {
            adapter.onRowClear(viewHolder)
        }
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
    }

    interface Listener {
        fun onRowMoved(fromPosition: Int, toPosition: Int)
        fun onRowSelected(itemViewHolder: DragDropRecyclerAdapter.ItemViewHolder)
        fun onRowClear(itemViewHolder: DragDropRecyclerAdapter.ItemViewHolder)
    }
}
5. Open main activity layout file and paste below code
<?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"
    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:id="@+id/recyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
6. Finally, Open main activity source file and add below code
package com.dragdroprecyclerview

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity(), OnStartDragListener {

    lateinit var adapter: DragDropRecyclerAdapter
    lateinit var touchHelper: ItemTouchHelper

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        adapter = DragDropRecyclerAdapter(this)
        populateListItem()

        val callback: ItemTouchHelper.Callback = ItemMoveCallbackListener(adapter)

        touchHelper = ItemTouchHelper(callback)
        touchHelper.attachToRecyclerView(recyclerView)

        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = adapter
    }

    override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
        touchHelper.startDrag(viewHolder)
    }

    private fun populateListItem() {
        val users = listOf(
            "Anuj",
            "Bhanu",
            "Chetan",
            "Devendra",
            "Esha",
            "Farmod",
            "Ganesh",
            "Hemant",
            "Ishaan",
            "Jack",
            "Kamal",
            "Lalit",
            "Mona"
        )
        adapter.setUsers(users)
    }


}

Conclusion

In this android example, We have learned the implementation Drag and drop RecyclerView item Android. I hope it’s helpful for you, then help me by sharing this post with all your friends.

Get Solution Code

Keep in touch

If you want to keep in touch and get an email when I write new blog posts, follow me on facebook or subscribe to us

Better way of debugging and logging your android application

6 Comments

  1. interface OnStartDragListener {
    fun onStartDrag(viewHolder: RecyclerView.ViewHolder)
    }

    • Holger Behrens

      Apologies for the noob question. Where do I put this?

      interface OnStartDragListener {

      fun onStartDrag(viewHolder: RecyclerView.ViewHolder)

      }

    • Holger Behrens

      OK I figured out that I needed to make a new listener class like this. However how do I initialize it?

    • adapter=DragDropRecyclerAdapter(this)
      

      you can use it in onCreate of your activity
      The reference ‘this’ will do the trick of initializing the interface callback, since it is implemented in the Activity.

  2. HI! thats a good example but it works?? I have’nt reference to “OnStartDragListener” . PLease help me

    • interface OnStartDragListener {

      fun onStartDrag(viewHolder: RecyclerView.ViewHolder)
      }

Write A Comment