Hello Friends, Today I am going to share how to add swipe to delete and undo feature in Android RecyclerView. Recently I was working on an app in which I was required to add same swipe to delete feature. So, I googled and found the solution and modified it according to the app. But here I am sharing copy of the code available at https://www.journaldev.com/23164/android-recyclerview-swipe-to-delete-undo with very minor modifications. But for the solution of the problem(swipe to delete), all the credit goes to Anupam Chugh @ journaldev.com
Now, here is my code
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
package com.zatackcoder.swipetodeleteandundo; import android.graphics.Color; import android.os.Bundle; import android.view.View; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.snackbar.Snackbar; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { RecyclerView itemsContainerRV; RecyclerViewAdapter itemAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); List<String> data = new ArrayList(); for(int i = 1; i <= 20; i++) { data.add("Item " + i); } itemsContainerRV = findViewById(R.id.itemsContainerRV); itemAdapter = new RecyclerViewAdapter(this, data); itemAdapter.notifyDataSetChanged(); itemsContainerRV.setAdapter(itemAdapter); ItemTouchHelper itemTouchhelper = new ItemTouchHelper(new SwipeToDeleteCallback(this) { @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) { final int position = viewHolder.getAdapterPosition(); final String item = itemAdapter.getData().get(position); itemAdapter.removeItem(position); Snackbar snackbar = Snackbar.make(itemsContainerRV, "Item was removed from the list.", Snackbar.LENGTH_LONG); snackbar.setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { itemAdapter.restoreItem(item, position); itemsContainerRV.scrollToPosition(position); } }); snackbar.setActionTextColor(Color.YELLOW); snackbar.show(); } }); itemTouchhelper.attachToRecyclerView(itemsContainerRV); } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?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" android:background="@color/cardview_dark_background"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/itemsContainerRV" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/> </androidx.constraintlayout.widget.ConstraintLayout> |
RecyclerViewAdapter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
package com.zatackcoder.swipetodeleteandundo; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.List; public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> { Context context; List<String> data; public RecyclerViewAdapter(Context context, List<String> data) { this.context = context; this.data = data; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v = LayoutInflater.from(context).inflate(R.layout.item, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) { holder.itemNameTV.setText(data.get(position)); holder.itemNameTV.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String item = data.get(position); Toast.makeText(context, "You clicked " + item, Toast.LENGTH_LONG).show(); } }); } @Override public int getItemCount() { return data.size(); } public void removeItem(int position) { data.remove(position); notifyItemRemoved(position); } public void restoreItem(String item, int position) { data.add(position, item); notifyItemInserted(position); } public List<String> getData() { return data; } static class ViewHolder extends RecyclerView.ViewHolder { View container; TextView itemNameTV; public ViewHolder(View view) { super(view); container = view; itemNameTV = view.findViewById(R.id.itemNameTV); } } } |
SwipeToDeleteCallback.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
package com.zatackcoder.swipetodeleteandundo; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.ItemTouchHelper; import android.view.View; public abstract class SwipeToDeleteCallback extends ItemTouchHelper.Callback { Context mContext; private Paint mClearPaint; private ColorDrawable mBackground; private int backgroundColor; private Drawable deleteDrawable; private int intrinsicWidth; private int intrinsicHeight; public SwipeToDeleteCallback(Context context) { mContext = context; mBackground = new ColorDrawable(); backgroundColor = Color.parseColor("#b80f0a"); mClearPaint = new Paint(); mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); deleteDrawable = ContextCompat.getDrawable(mContext, android.R.drawable.ic_menu_delete); intrinsicWidth = deleteDrawable.getIntrinsicWidth(); intrinsicHeight = deleteDrawable.getIntrinsicHeight(); } @Override public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { return makeMovementFlags(0, ItemTouchHelper.LEFT); } @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) { return false; } @Override public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); View itemView = viewHolder.itemView; int itemHeight = itemView.getHeight(); boolean isCancelled = dX == 0 && !isCurrentlyActive; if (isCancelled) { clearCanvas(c, itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom()); super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); return; } mBackground.setColor(backgroundColor); mBackground.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom()); mBackground.draw(c); int deleteIconTop = itemView.getTop() + (itemHeight - intrinsicHeight) / 2; int deleteIconMargin = (itemHeight - intrinsicHeight) / 2; int deleteIconLeft = itemView.getRight() - deleteIconMargin - intrinsicWidth; int deleteIconRight = itemView.getRight() - deleteIconMargin; int deleteIconBottom = deleteIconTop + intrinsicHeight; deleteDrawable.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom); deleteDrawable.draw(c); super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } private void clearCanvas(Canvas c, Float left, Float top, Float right, Float bottom) { c.drawRect(left, top, right, bottom, mClearPaint); } @Override public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) { return 0.8f; } } |
item.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:layout_marginTop="4dp" android:layout_marginLeft="2dp" android:layout_marginRight="2dp" android:background="#FFFFFF"> <TextView android:id="@+id/itemNameTV" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" android:textStyle="bold" android:textColor="#000000" android:text="Item"/> </LinearLayout > |
Video
AndroidStudio Project Download
Thanks for Stoping by
If you find this helpful then please share
Comments