Android - Swipe to delete RecyclerView

Solution 1:

Simple Code for RecyclerView Swipe:

     ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT | ItemTouchHelper.DOWN | ItemTouchHelper.UP) {

            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                Toast.makeText(ListActivity.this, "on Move", Toast.LENGTH_SHORT).show();
                return false;
            }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
                Toast.makeText(ListActivity.this, "on Swiped ", Toast.LENGTH_SHORT).show();
                //Remove swiped item from list and notify the RecyclerView
                int position = viewHolder.getAdapterPosition();
                arrayList.remove(position);
                adapter.notifyDataSetChanged();

            }
     };

Then set callback for recyclerView with below statements:

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
 itemTouchHelper.attachToRecyclerView(rv);

Solution 2:

I had to do this the other day and I had some issues so I decided to write a blog post on it. No 3rd party lib necessary.

  • Blog post
  • GitHub repo

Basically, you wouldn't draw the "undo state" via onChildDraw, it would be done via ViewHolder. Also you wouldn't actually delete row in onSwipe just mark it as "pending delete" and notify adapter to rebind it in "undo state". At the same time you post a Runnable actually removing the row in x seconds unless undo button is pressed...

Solution 3:

Here's the minimum code in your onCreate that sets up "Swipe Left to Delete":

binding.rows.adapter = adapter
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
    override fun onMove(v: RecyclerView, h: RecyclerView.ViewHolder, t: RecyclerView.ViewHolder) = false
    override fun onSwiped(h: RecyclerView.ViewHolder, dir: Int) = adapter.removeAt(h.adapterPosition)
}).attachToRecyclerView(binding.rows)

This assumes your Adapter class has a removeAt function. Mine looks like this:

fun removeAt(index: Int) {
    items.removeAt(index)   // items is a MutableList
    notifyItemRemoved(index)
}

Thanks @RahulRaina for your Java answer!

Solution 4:

You can try Swipeable-RecyclerView

    SwipeableRecyclerView rv = findViewById(R.id.rv);
    rv.setLayoutManager(new LinearLayoutManager(this));
    rv.setAdapter(mAdapter);

    rv.setListener(new SwipeLeftRightCallback.Listener() {
        @Override
        public void onSwipedLeft(int position) {
            mList.remove(position);
            mAdapter.notifyDataSetChanged();
        }

        @Override
        public void onSwipedRight(int position) {
            mList.remove(position);
            mAdapter.notifyDataSetChanged();
        }
    });

xml for two sides swipe

<com.tsuryo.swipeablerv.SwipeableRecyclerView
    android:id="@+id/rv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:leftBgColor="@color/colorAccent"
    app:leftImage="@drawable/ic_remove"
    app:leftText="Delete"
    app:rightBgColor="@color/blue"
    app:rightImage="@drawable/ic_check"
    app:rightText="Read"
    app:textColor="@android:color/white"
    app:textSize="20sp" />