Dark Mode
Image

Android Fragments

Android Service

Android AlarmManager

Camera Tutorial

Sensor Tutorial

Android Graphics

Android Animation

Android Web Service

Android MCQ

Android Quiz

Swipe to Delete RecyclerView items with UNDU

In this tutorial, we will create the example to delete an item of RecyclerView by swiping the item with undo functionality. For this purpose, we will use ItemTouchHelper class which is added in Android Support Library V7. This class is used to create a swipe to delete the items of RecyclerView. It has a SimpleCallback class that configures the events which are performed to swipe or move the item of the RecyclerView.

ItemTouchHelper class
It is a utility class which provides the facility to add swipe to dismiss and drag & drops the items of RecyclerView. It overrides the callback methods onMove() or onSwipe() depending upon the functionality we implement.

Android Swipe to Delete RecyclerView items Example
Create a MainActivity.java class with the following code.

activity_main.xml

ass with the following code.  
activity_main.xml  
<?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"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:fitsSystemWindows="true"  
    tools:context="example.javatpoint.com.recyclerviewswipedeleteundo.MainActivity">  
  
    <android.support.design.widget.AppBarLayout  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:theme="@style/AppTheme.AppBarOverlay">  
  
        <android.support.v7.widget.Toolbar  
            android:id="@+id/toolbar"  
            android:layout_width="match_parent"  
            android:layout_height="?attr/actionBarSize"  
            android:background="?attr/colorPrimary"  
            app:popupTheme="@style/AppTheme.PopupOverlay" />  
  
    </android.support.design.widget.AppBarLayout>  
  
    <include layout="@layout/content_main" />  
  
</android.support.design.widget.CoordinatorLayout>  
 

content_main.xml

<fragment 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:id="@+id/fragment"  
    android:name="example.javatpoint.com.recyclerviewswipedeleteundo.MainActivityFragment"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    app:layout_behavior="@string/appbar_scrolling_view_behavior"  
    tools:layout="@layout/fragment_main" />  

MainActivity.java

package example.javatpoint.com.recyclerviewswipedeleteundo;  
  
import android.os.Bundle;  
import android.support.v7.app.AppCompatActivity;  
import android.support.v7.widget.Toolbar;  
  
public class MainActivity extends AppCompatActivity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);  
        setSupportActionBar(toolbar);  
  
    }  
}  

Create a layout regular_item.xml which appears at normal mode.

regular_item.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:id="@+id/regularLayout"  
    android:layout_width="match_parent"  
    android:layout_height="wrap_content"  
    android:orientation="vertical"  
    android:padding="@dimen/activity_horizontal_margin">  
  
    <TextView  
        android:id="@+id/list_item"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:text="Regular Layout"  
        android:textSize="28sp" />  
</LinearLayout>  

Create a layout swipe_item.xml which appears at the period of swipe item.

swipe_item.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:id="@+id/swipeLayout"  
    android:layout_width="match_parent"  
    android:layout_height="wrap_content"  
    android:background="@color/swipebackground"  
    android:orientation="horizontal"  
    android:padding="@dimen/activity_horizontal_margin"  
    android:visibility="visible"  
    android:weightSum="3">  
  
    <TextView  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_weight="1"  
        android:text="@string/archived_label"  
        android:textColor="@android:color/white"  
        android:textSize="24sp" />  
  
  
    <TextView  
        android:id="@+id/undo"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_weight="2"  
        android:gravity="end"  
        android:paddingBottom="5dp"  
        android:paddingLeft="16dp"  
        android:paddingRight="16dp"  
        android:paddingTop="5dp"  
        android:text="@string/undo_label"  
        android:textColor="@android:color/white"  
        android:textSize="22sp"  
        android:textStyle="bold" />  
  
</LinearLayout> 

customlayout.xml

<?xml version="1.0" encoding="utf-8"?>  
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="wrap_content">  
    <!-- Swipe Layout-->  
    <include layout="@layout/swipe_item" />  
    <!-- Regular Layout-->  
    <include layout="@layout/regular_item" />  
</FrameLayout> 

Create a utility class SwipeUtil.java which extends the ItemTouchHelper.SimpleCallback class and overrides its onMove(), onSwiped(), onChildDraw() methods. The onSwiped() method is called when we perform swipe operation on an item, and the onChildDraw() methods contain the implementation logic of drawing canvas while swiping the items of RecyclerView.

SwipeUtil.java

<?xml version="1.0" encoding="utf-8"?>  
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="wrap_content">  
    <!-- Swipe Layout-->  
    <include layout="@layout/swipe_item" />  
    <!-- Regular Layout-->  
    <include layout="@layout/regular_item" />  
</FrameLayout>

Create an ItemViewHolder.java class and extends RecyclerView.ViewHolder.

ItemViewHolder.java

package example.javatpoint.com.recyclerviewswipedeleteundo;  
  
import android.support.v7.widget.RecyclerView;  
import android.view.View;  
import android.widget.LinearLayout;  
import android.widget.TextView;  
  
public class ItemViewHolder extends RecyclerView.ViewHolder {  
  
    public LinearLayout regularLayout;  
    public LinearLayout swipeLayout;  
    public TextView listItem;  
    public TextView undo;  
  
    public ItemViewHolder(View view) {  
        super(view);  
  
        regularLayout = view.findViewById(R.id.regularLayout);  
        listItem =  view.findViewById(R.id.list_item);  
        swipeLayout = view.findViewById(R.id.swipeLayout);  
        undo =  view.findViewById(R.id.undo);  
    }  
}  
 

Create an adapter class MyAdapter.java which extends the RecyclerView.Adapter class and overrides its onCreateViewHolder(), onBindViewHolder() methods.

MyAdapter.java

package example.javatpoint.com.recyclerviewswipedeleteundo;  
  
import android.os.Handler;  
import android.support.v7.widget.RecyclerView;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
  
public class MyAdapter extends RecyclerView.Adapter<ItemViewHolder> {  
  
    private List<String> dataList;  
    private List<String> itemsPendingRemoval;  
  
    private static final int PENDING_REMOVAL_TIMEOUT = 3000; // 3sec  
    private Handler handler = new Handler(); // hanlder for running delayed runnables  
    HashMap<String, Runnable> pendingRunnables = new HashMap<>(); // map of items to pending runnable, to cancel the removal  
  
  
    public MyAdapter(List<String> dataList) {  
        this.dataList = dataList;  
        itemsPendingRemoval = new ArrayList<>();  
    }  
  
    @Override  
    public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.customlayout, parent, false);  
        return new ItemViewHolder(itemView);  
    }  
  
    @Override  
    public void onBindViewHolder(ItemViewHolder itemViewHolder, int position) {  
  
        final String data = dataList.get(position);  
  
        if (itemsPendingRemoval.contains(data)) {  
            /** show swipe layout and hide regular layout */  
            itemViewHolder.regularLayout.setVisibility(View.GONE);  
            itemViewHolder.swipeLayout.setVisibility(View.VISIBLE);  
            itemViewHolder.undo.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    undoOpt(data);  
                }  
            });  
        } else {  
            /** show regular layout and hide swipe layout*/  
            itemViewHolder.regularLayout.setVisibility(View.VISIBLE);  
            itemViewHolder.swipeLayout.setVisibility(View.GONE);  
            itemViewHolder.listItem.setText(data);  
        }  
    }  
  
    private void undoOpt(String customer) {  
        Runnable pendingRemovalRunnable = pendingRunnables.get(customer);  
        pendingRunnables.remove(customer);  
        if (pendingRemovalRunnable != null)  
            handler.removeCallbacks(pendingRemovalRunnable);  
        itemsPendingRemoval.remove(customer);  
        // this will rebind the row in "normal" state  
        notifyItemChanged(dataList.indexOf(customer));  
    }  
  
    @Override  
    public int getItemCount() {  
        return dataList.size();  
    }  
  
    public void pendingRemoval(int position) {  
  
        final String data = dataList.get(position);  
        if (!itemsPendingRemoval.contains(data)) {  
            itemsPendingRemoval.add(data);  
            // this will redraw row in "undo" state  
            notifyItemChanged(position);  
            //create, store and post a runnable to remove the data  
            Runnable pendingRemovalRunnable = new Runnable() {  
                @Override  
                public void run() {  
                    remove(dataList.indexOf(data));  
                }  
            };  
            handler.postDelayed(pendingRemovalRunnable, PENDING_REMOVAL_TIMEOUT);  
            pendingRunnables.put(data, pendingRemovalRunnable);  
        }  
    }  
  
    public void remove(int position) {  
        String data = dataList.get(position);  
        if (itemsPendingRemoval.contains(data)) {  
            itemsPendingRemoval.remove(data);  
        }  
        if (dataList.contains(data)) {  
            dataList.remove(position);  
            notifyItemRemoved(position);  
        }  
    }  
  
    public boolean isPendingRemoval(int position) {  
        String data = dataList.get(position);  
        return itemsPendingRemoval.contains(data);  
    }  
}  

Create a MainActivityFragment.java class and extends the Fragment class. In this class, set the adapter MyAdapter.java class and utility SwipeUtil.java class.

fragment_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:paddingBottom="@dimen/activity_vertical_margin"  
    android:paddingLeft="@dimen/activity_horizontal_margin"  
    android:paddingRight="@dimen/activity_horizontal_margin"  
    android:paddingTop="@dimen/activity_vertical_margin"  
    tools:context="example.javatpoint.com.recyclerviewswipedeleteundo.MainActivityFragment"  
    tools:showIn="@layout/activity_main">  
  
    <android.support.v7.widget.RecyclerView  
        android:id="@+id/recyclerView"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"/>  
</RelativeLayout>

MainActivityFragment.java

package example.javatpoint.com.recyclerviewswipedeleteundo;  
  
import android.support.v4.app.Fragment;  
import android.os.Bundle;  
import android.support.v4.content.ContextCompat;  
import android.support.v7.widget.LinearLayoutManager;  
import android.support.v7.widget.RecyclerView;  
import android.support.v7.widget.helper.ItemTouchHelper;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import java.util.ArrayList;  
import java.util.List;  
  
public class MainActivityFragment extends Fragment {  
  
    private RecyclerView mRecyclerView;  
    private MyAdapter myAdapter;  
    String[] listValue = {"C Tutorial","C++ Tutorial","Data Structure","Java Tutorial","Android Example","Kotlin Programing","Python language","Ruby Tutorial",".Net Tutorial","MySQL Database"};  
    public MainActivityFragment() {  
    }  
  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
                             Bundle savedInstanceState) {  
        View mView = inflater.inflate(R.layout.fragment_main, container, false);  
        mRecyclerView = mView.findViewById(R.id.recyclerView);  
        return mView;  
    }  
  
    @Override  
    public void onResume() {  
        super.onResume();  
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());  
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);  
        mRecyclerView.setLayoutManager(linearLayoutManager);  
        myAdapter = new MyAdapter(getData());  
        mRecyclerView.setAdapter(myAdapter);  
  
        setSwipeForRecyclerView();  
    }  
  
    private List<String> getData() {  
        List<String> modelList = new ArrayList<>();  
        for (int i = 0; i < listValue.length; i++) {  
            modelList.add(listValue[i]);  
        }  
        return modelList;  
    }  
  
    private void setSwipeForRecyclerView() {  
  
        SwipeUtil swipeHelper = new SwipeUtil(0, ItemTouchHelper.LEFT, getActivity()) {  
            @Override  
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {  
                int swipedPosition = viewHolder.getAdapterPosition();  
                myAdapter = (MyAdapter)mRecyclerView.getAdapter();  
                myAdapter.pendingRemoval(swipedPosition);  
            }  
  
            @Override  
            public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {  
                int position = viewHolder.getAdapterPosition();  
                myAdapter = (MyAdapter) mRecyclerView.getAdapter();  
               if (myAdapter.isPendingRemoval(position)) {  
                     return 0;  
                }  
                return super.getSwipeDirs(recyclerView, viewHolder);  
            }  
        };  
  
        ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(swipeHelper);  
        mItemTouchHelper.attachToRecyclerView(mRecyclerView);  
        //set swipe label  
        swipeHelper.setLeftSwipeLable("Archive");  
        //set swipe background-Color  
        swipeHelper.setLeftcolorCode(ContextCompat.getColor(getActivity(), R.color.swipebackground));  
    }  
}  

strings.xml

<resources>  
    <string name="app_name">RecyclerView SwipeDeleteUndo</string>  
    <string name="action_settings">Settings</string>  
    <string name="hello_blank_fragment">Hello blank fragment</string>  
    <string name="undo_label"><u>Undo</u></string>  
    <string name="archived_label">Archive</string>  
</resources>

dimens.xml

<resources>  
    <dimen name="fab_margin">16dp</dimen>  
    <dimen name="activity_horizontal_margin">16dp</dimen>  
    <dimen name="activity_vertical_margin">16dp</dimen>  
    <dimen name="ic_clear_margin">56dp</dimen>  
    <dimen name="text_size_medium">20sp</dimen>  
</resources>

colors.xml

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <color name="colorPrimary">#3F51B5</color>  
    <color name="colorPrimaryDark">#303F9F</color>  
    <color name="colorAccent">#FF4081</color>  
    <color name="swipebackground">#cf0b4e</color>  
</resources>     

Output:

Android Swipe to Delete RecyclerView items with UNDU Android Swipe to Delete RecyclerView items with UNDU Android Swipe to Delete RecyclerView items with UNDU

Comment / Reply From