Introduction
In this article, we’re going to learn how to implement drag and drop reordering inside a recyclerView.
Here, we implement dragging and dropping to reorganise the items in the recyclerView; simply long-press an item to drag it and drop it in the desired location.
Here, we first create the recyclerview using static data, and then we use the ItemTouchHelper to implement the drag and drop functionality.
Create Drag-and-Drop Recyclerview in Android
Step 1
Create a new project in the Android Studio and select an empty activity.
Step 2
Give the project a name, select the save location folder, and click on the finish button.
Step 3
Create the activity_main.xml file as shown below.
<?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="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Step 4
Create the recycler_row.xml file in the layout folder for the recyclerview item.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
app:cardBackgroundColor="#12dddd"
app:cardCornerRadius="5dp"
app:cardElevation="5dp"
app:cardMaxElevation="5dp"
app:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/lblItemName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:text="Item Name"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/lblItemDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/lblItemName"
android:layout_marginStart="10dp"
android:layout_marginTop="15dp"
android:drawablePadding="2dp"
android:padding="5dp"
android:text="Item Details" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
Step 5
Create the ItemModel.java class for item details that stores the item's name and its subdetails.
package com.uday.recyclerviewdragdrop;
public class ItemModel {
private String Name;
private String Detail;
public ItemModel(String name, String detail) {
Name = name;
Detail = detail;
}
public String getName() {
return Name;
}
public String getDetail() {
return Detail;
}
}
Step 6
Create the RecyclerViewAdapter.java class as follows:
package com.uday.recyclerviewdragdrop;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.Collections;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewModel>
{
private List<ItemModel> dataList;
public void setDataList(List<ItemModel> dataList){
this.dataList = dataList;
}
@NonNull
@Override
public MyViewModel onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row,parent,false);
return new MyViewModel(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewModel holder, int position) {
holder.lblItemName.setText(dataList.get(position).getName());
holder.lblItemDetails.setText(dataList.get(position).getDetail());
}
@Override
public int getItemCount() {
return dataList.size();
}
class MyViewModel extends RecyclerView.ViewHolder{
TextView lblItemName,lblItemDetails;
CardView cardView;
public MyViewModel(@NonNull View itemView) {
super(itemView);
lblItemName = itemView.findViewById(R.id.lblItemName);
lblItemDetails = itemView.findViewById(R.id.lblItemDetails);
cardView = itemView.findViewById(R.id.cardView);
}
}
}
Step 7
Create RecyclerRowMoveCallback.java and extends ItemTouchHelper.Callback as follows:
package com.uday.recyclerviewdragdrop;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
public class RecyclerRowMoveCallback extends ItemTouchHelper.Callback {
private RecyclerViewRowTouchHelperContract touchHelperContract;
public RecyclerRowMoveCallback(RecyclerViewRowTouchHelperContract touchHelperContract){
this.touchHelperContract = touchHelperContract;
}
@Override
public boolean isLongPressDragEnabled() {
return true;
}
@Override
public boolean isItemViewSwipeEnabled() {
return false;
}
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(dragFlag,0);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
this.touchHelperContract.onRowMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());
return false;
}
@Override
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
if(actionState != ItemTouchHelper.ACTION_STATE_IDLE)
{
if(viewHolder instanceof RecyclerViewAdapter.MyViewModel){
RecyclerViewAdapter.MyViewModel myViewHolder = (RecyclerViewAdapter.MyViewModel)viewHolder;
touchHelperContract.onRowSelected(myViewHolder);
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if(viewHolder instanceof RecyclerViewAdapter.MyViewModel){
RecyclerViewAdapter.MyViewModel myViewHolder = (RecyclerViewAdapter.MyViewModel)viewHolder;
touchHelperContract.onRowClear(myViewHolder);
}
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
public interface RecyclerViewRowTouchHelperContract{
void onRowMoved(int from,int to);
void onRowSelected(RecyclerViewAdapter.MyViewModel myViewHolder);
void onRowClear(RecyclerViewAdapter.MyViewModel myViewHolder);
}
}
Step 8
Now implement the interface RecyclerRowMoveCallback.RecyclerViewRowTouchHelperContract in the RecyclerViewAdapter class. So after that, your adapter files look like the following:
package com.uday.recyclerviewdragdrop;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.Collections;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewModel>
implements RecyclerRowMoveCallback.RecyclerViewRowTouchHelperContract{
private List<ItemModel> dataList;
public void setDataList(List<ItemModel> dataList){
this.dataList = dataList;
}
@NonNull
@Override
public MyViewModel onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row,parent,false);
return new MyViewModel(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewModel holder, int position) {
holder.lblItemName.setText(dataList.get(position).getName());
holder.lblItemDetails.setText(dataList.get(position).getDetail());
}
@Override
public int getItemCount() {
return dataList.size();
}
@Override
public void onRowMoved(int from, int to) {
if(from < to)
{
for(int i=from; i<to; i++)
{
Collections.swap(dataList,i,i+1);
}
}
else
{
for(int i=from; i>to; i--)
{
Collections.swap(dataList,i,i-1);
}
}
notifyItemMoved(from,to);
}
@Override
public void onRowSelected(MyViewModel myViewHolder) {
myViewHolder.cardView.setCardBackgroundColor(Color.GRAY);
}
@Override
public void onRowClear(MyViewModel myViewHolder) {
myViewHolder.cardView.setCardBackgroundColor(Color.parseColor("#12dddd"));
}
class MyViewModel extends RecyclerView.ViewHolder{
TextView lblItemName,lblItemDetails;
CardView cardView;
public MyViewModel(@NonNull View itemView) {
super(itemView);
lblItemName = itemView.findViewById(R.id.lblItemName);
lblItemDetails = itemView.findViewById(R.id.lblItemDetails);
cardView = itemView.findViewById(R.id.cardView);
}
}
}
Step 9
Now add the following code in MainActivity.java class
package com.uday.recyclerviewdragdrop;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
private ArrayList<ItemModel> list = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Create Data For Recyclerview
list.add(new ItemModel("Item 1","Item Detail 1"));
list.add(new ItemModel("Item 2","Item Detail 2"));
list.add(new ItemModel("Item 3","Item Detail 3"));
list.add(new ItemModel("Item 4","Item Detail 4"));
list.add(new ItemModel("Item 5","Item Detail 5"));
list.add(new ItemModel("Item 6","Item Detail 6"));
list.add(new ItemModel("Item 7","Item Detail 7"));
list.add(new ItemModel("Item 8","Item Detail 8"));
list.add(new ItemModel("Item 9","Item Detail 9"));
recyclerView = findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
RecyclerViewAdapter adapter = new RecyclerViewAdapter();
adapter.setDataList(list);
ItemTouchHelper.Callback callback = new RecyclerRowMoveCallback(adapter);
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(recyclerView);
recyclerView.setAdapter(adapter);
}
}
Step 10
Now run your app and drag and drop the item.
Summary
As you can see, the implementation of drag and drop reordering inside a recyclerView in Android is very simple.
In this article, we learned how to create a drag-and-drop recyclerview in Android.
And here I have also uploaded a demo project, so you can download it and try it for yourself.
Thank you for reading my article. Please leave your comments in the comment box below.
Enjoy Coding