Android RecyclerView Swipe To Delete Example Tutorial is explained here.
We will make a recyclerview such that user swipe to show button, which will delete the row.
Android RecyclerView Swipe to delete example is similar like gmail app.
We will also implement an UNDO feature, which will restore the deleted row item.
Also Read,
First, check the output of the example, then we will create it with android studio.
Step 1. Create a new project.
Always try to create new project with empty activity in android studio.
Step 2. Make row item layout
Prepare new layout resource file named rv_item.xml
Copy following source code in it
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="5dp" android:paddingLeft="5dp" android:paddingRight="5dp" tools:context=".MainActivity" tools:ignore="NamespaceTypo"> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="90dp" android:layout_gravity="center" app:cardBackgroundColor="#ffffff" android:layout_marginTop="0dp" card_view:cardCornerRadius="1dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/tv" android:height="90dp" android:gravity="center" android:paddingLeft="10dp" android:text="Image" android:textColor="#000" android:textStyle="bold" android:textSize="18sp" /> </LinearLayout> </android.support.v7.widget.CardView> </RelativeLayout>
This layout file rv_item.xml file represents the layout for each row of recyclerview.
Here, we will create simple row item with just one text in it.
TextView is added to show the name of the row item.
Step 3. Update gradle file
Add below lines in your build.module(Module:app) file
compile 'com.android.support:recyclerview-v7:27.1.1' compile 'com.android.support:cardview-v7:27.1.1' compile 'com.android.support:design:27.1.1'
Above three lines add the required classes for recyclerview, cardview and material design respectively.
Step 4. Making Model Class
Make a new JAVA class and give it a name Model.java
Add below code in it
/** * Created by Parsania Hardik on 28-Jun-17. */ public class Model { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Model class is something like a data transporter for recyclerview.
An object of model class is created for each row item of recyclerview then, all these objects are stored in an ArrayList.
Finally, ArayList will populate the recyclerview in Adapter class.
Step 5. Creating Adapter
A java class named Adapter.java will contain below source code. Go ahead and make new java class.
import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; /** * Created by Parsania Hardik on 26-Jun-17. */ public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> { private LayoutInflater inflater; private ArrayList<Model> imageModelArrayList; public Adapter(Context ctx, ArrayList<Model> imageModelArrayList){ inflater = LayoutInflater.from(ctx); this.imageModelArrayList = imageModelArrayList; } public void removeItem(int position) { imageModelArrayList.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, imageModelArrayList.size()); } public void restoreItem(Model model, int position) { imageModelArrayList.add(position, model); // notify item added by position notifyItemInserted(position); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.rv_item, parent, false); MyViewHolder holder = new MyViewHolder(view); return holder; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.time.setText(imageModelArrayList.get(position).getName()); } @Override public int getItemCount() { return imageModelArrayList.size(); } class MyViewHolder extends RecyclerView.ViewHolder{ TextView time; public MyViewHolder(View itemView) { super(itemView); time = (TextView) itemView.findViewById(R.id.tv); } } }
Adapter will populate the RecyclerView with the help of ArrayList of Model objets.
Two methods of adapter are important here.
Understanding removeItem()
This method will remove the row item when user swipes left or right.
Look at below code
public void removeItem(int position) { imageModelArrayList.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, imageModelArrayList.size()); }
When user swipes left or right, this method will be called from MainActivity.java class along with the position as a parameter.
You can see in above code that an object of model class is removed from ArrayList who is present at position given by parameter.
Understanding resoreItem()
This method will restore the deleted item, when user clicks on UNDO.
Look at following code
public void restoreItem(Model model, int position) { imageModelArrayList.add(position, model); // notify item added by position notifyItemInserted(position); }
When user clicks on UNDO, a model object which was deleted and a position will be passed from Main Activity.
Then, model object will be added at the required position which was also passed from Main Activity as a parameter.
Step 6. Updating MainActivity
Update activity_main.xml as below
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/linear" android:background="#e4e0e0" tools:context=".MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="10dp"/> </android.support.design.widget.CoordinatorLayout>
Update MainActivity.java class as following
import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.graphics.Canvas; import java.util.ArrayList; import android.support.v7.widget.helper.ItemTouchHelper; public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private ArrayList<Model> imageModelArrayList; private Adapter adapter; private Paint p = new Paint(); private String[] myImageNameList = new String[]{"Benz", "Bike", "Car","Carrera" ,"Ferrari","Harly", "Lamborghini","Silver"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.recycler); imageModelArrayList = populateList(); adapter = new Adapter(this,imageModelArrayList); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false)); enableSwipe(); } private void enableSwipe(){ ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { int position = viewHolder.getAdapterPosition(); if (direction == ItemTouchHelper.LEFT){ final Model deletedModel = imageModelArrayList.get(position); final int deletedPosition = position; adapter.removeItem(position); // showing snack bar with Undo option Snackbar snackbar = Snackbar.make(getWindow().getDecorView().getRootView(), " removed from Recyclerview!", Snackbar.LENGTH_LONG); snackbar.setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { // undo is selected, restore the deleted item adapter.restoreItem(deletedModel, deletedPosition); } }); snackbar.setActionTextColor(Color.YELLOW); snackbar.show(); } else { final Model deletedModel = imageModelArrayList.get(position); final int deletedPosition = position; adapter.removeItem(position); // showing snack bar with Undo option Snackbar snackbar = Snackbar.make(getWindow().getDecorView().getRootView(), " removed from Recyclerview!", Snackbar.LENGTH_LONG); snackbar.setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { // undo is selected, restore the deleted item adapter.restoreItem(deletedModel, deletedPosition); } }); snackbar.setActionTextColor(Color.YELLOW); snackbar.show(); } } @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { Bitmap icon; if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){ View itemView = viewHolder.itemView; float height = (float) itemView.getBottom() - (float) itemView.getTop(); float width = height / 3; if(dX > 0){ p.setColor(Color.parseColor("#388E3C")); RectF background = new RectF((float) itemView.getLeft(), (float) itemView.getTop(), dX,(float) itemView.getBottom()); c.drawRect(background,p); icon = BitmapFactory.decodeResource(getResources(), R.drawable.delete); RectF icon_dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width,(float) itemView.getLeft()+ 2*width,(float)itemView.getBottom() - width); c.drawBitmap(icon,null,icon_dest,p); } else { p.setColor(Color.parseColor("#D32F2F")); RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(),(float) itemView.getRight(), (float) itemView.getBottom()); c.drawRect(background,p); icon = BitmapFactory.decodeResource(getResources(), R.drawable.delete); RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width,(float) itemView.getRight() - width,(float)itemView.getBottom() - width); c.drawBitmap(icon,null,icon_dest,p); } } super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } }; ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback); itemTouchHelper.attachToRecyclerView(recyclerView); } private ArrayList<Model> populateList(){ ArrayList<Model> list = new ArrayList<>(); for(int i = 0; i < 8; i++){ Model imageModel = new Model(); imageModel.setName(myImageNameList[i]); list.add(imageModel); } return list; } }
Understanding unableSwipe() method
Refer below code
private void enableSwipe(){ ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { int position = viewHolder.getAdapterPosition(); if (direction == ItemTouchHelper.LEFT){ final Model deletedModel = imageModelArrayList.get(position); final int deletedPosition = position; adapter.removeItem(position); // showing snack bar with Undo option Snackbar snackbar = Snackbar.make(getWindow().getDecorView().getRootView(), " removed from Recyclerview!", Snackbar.LENGTH_LONG); snackbar.setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { // undo is selected, restore the deleted item adapter.restoreItem(deletedModel, deletedPosition); } }); snackbar.setActionTextColor(Color.YELLOW); snackbar.show(); } else { final Model deletedModel = imageModelArrayList.get(position); final int deletedPosition = position; adapter.removeItem(position); // showing snack bar with Undo option Snackbar snackbar = Snackbar.make(getWindow().getDecorView().getRootView(), " removed from Recyclerview!", Snackbar.LENGTH_LONG); snackbar.setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { // undo is selected, restore the deleted item adapter.restoreItem(deletedModel, deletedPosition); } }); snackbar.setActionTextColor(Color.YELLOW); snackbar.show(); } } @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { Bitmap icon; if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){ View itemView = viewHolder.itemView; float height = (float) itemView.getBottom() - (float) itemView.getTop(); float width = height / 3; if(dX > 0){ p.setColor(Color.parseColor("#388E3C")); RectF background = new RectF((float) itemView.getLeft(), (float) itemView.getTop(), dX,(float) itemView.getBottom()); c.drawRect(background,p); icon = BitmapFactory.decodeResource(getResources(), R.drawable.delete); RectF icon_dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width,(float) itemView.getLeft()+ 2*width,(float)itemView.getBottom() - width); c.drawBitmap(icon,null,icon_dest,p); } else { p.setColor(Color.parseColor("#D32F2F")); RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(),(float) itemView.getRight(), (float) itemView.getBottom()); c.drawRect(background,p); icon = BitmapFactory.decodeResource(getResources(), R.drawable.delete); RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width,(float) itemView.getRight() - width,(float)itemView.getBottom() - width); c.drawBitmap(icon,null,icon_dest,p); } } super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } }; ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback); itemTouchHelper.attachToRecyclerView(recyclerView); }
This method will detect the swipe movement(left or right) of the user.
Then method will decide whether user have swipe left or right. Here, we are deleting row item on both swipe, but you can update them as per your requirement.
After removing the row item, a snackbar will be shown at the bottom of the screen.
This snackbar contains the UNDO button, which can be used to restore the deleted row item.
So it was all about creating Swipe to delete in recyclerview.
If you want to use third party library, then you can use below github library.
https://github.com/hudomju/android-swipe-to-dismiss-undo
But, it is better not to use third party library as it increases the apk file size.
Share our articles with other learners to help them in their journey.
Cheers and Happy coding! š
Download Source Code For Android RecyclerView Swipe To Delete
Click on below link to download android studio source code.
[sociallocker]RecyclerView Swipe To Delete[/sociallocker]