Android Swipe untuk Hapus RecyclerView item dengan UNDO

Dalam tutorial ini, kita akan membuat contoh untuk menghapus item RecyclerView dengan menggesekkan item dengan fungsi undo. Untuk tujuan ini, kita akan menggunakan kelas ItemTouchHelper yang ditambahkan di Android Support Library V7. Kelas ini digunakan untuk membuat gesekan untuk menghapus item RecyclerView. Ini memiliki kelas SimpleCallback yang mengkonfigurasi peristiwa yang dilakukan untuk menggesek atau memindahkan item RecyclerView.

Kelas ItemTouchHelper

Ini adalah kelas utilitas yang menyediakan fasilitas untuk menambahkan gesekan untuk mengabaikan dan menyeret dan menjatuhkan item RecyclerView. Ini menimpa metode callback onMove() atau onSwipe() tergantung pada fungsi yang kita terapkan.

Contoh Android Swipe untuk Hapus RecyclerView item

Buat kelas MainActivity.java dengan kode berikut.

File : 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.android.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>  


File : 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.android.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" />  


File : MainActivity.java

package example.android.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);  
 
    }  
}  


Buat layout regular_item.xml yang muncul pada mode normal.

File : 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>  


Buat layout swipe_item.xml yang muncul pada periode item gesek.

File : 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>  


File : 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>  


Buat kelas utilitas SwipeUtil.java yang memperluas kelas ItemTouchHelper.SimpleCallback dan menimpa metode onMove(), onSwiped(), onChildDraw(). Metode onSwiped() disebut ketika kita melakukan operasi gesek pada item, dan metode onChildDraw() berisi logika implementasi menggambar kanvas sambil menggesek item RecyclerView.

File : SwipeUtil.java

package example.android.com.recyclerviewswipedeleteundo;  
 
import android.content.Context;  
import android.graphics.Canvas;  
import android.graphics.Color;  
import android.graphics.Paint;  
import android.graphics.PorterDuff;  
import android.graphics.drawable.ColorDrawable;  
import android.graphics.drawable.Drawable;  
import android.support.v4.content.ContextCompat;  
import android.support.v7.widget.RecyclerView;  
import android.support.v7.widget.helper.ItemTouchHelper;  
import android.view.View;  
 
public abstract class SwipeUtil extends ItemTouchHelper.SimpleCallback {  
 
    private Drawable background;  
    private Drawable deleteIcon;  
    private int xMarkMargin;  
    private boolean initiated;  
    private Context context;  
    private int leftcolorCode;  
    private String leftSwipeLable;  
 
    public SwipeUtil(int dragDirs, int swipeDirs, Context context) {  
        super(dragDirs, swipeDirs);  
        this.context = context;  
    }  
 
    private void init() {  
        background = new ColorDrawable();  
        xMarkMargin = (int) context.getResources().getDimension(R.dimen.ic_clear_margin);  
        deleteIcon = ContextCompat.getDrawable(context, android.R.drawable.ic_menu_delete);  
        deleteIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);  
        initiated = true;  
    }  
 
    @Override  
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {  
        return false;  
    }  
 
    @Override  
    public abstract void onSwiped(RecyclerView.ViewHolder viewHolder, int direction);  
 
    @Override  
    public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {  
 
        return super.getSwipeDirs(recyclerView, viewHolder);  
    }  
 
    @Override  
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,  
                            float dX, float dY, int actionState, boolean isCurrentlyActive) {  
 
        View itemView = viewHolder.itemView;  
        if (!initiated) {  
            init();  
        }  
 
        int itemHeight = itemView.getBottom() - itemView.getTop();  
        //Setting Swipe Background  
        ((ColorDrawable) background).setColor(getLeftcolorCode());  
        background.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom());  
        background.draw(c);  
 
        int intrinsicWidth = deleteIcon.getIntrinsicWidth();  
        int intrinsicHeight = deleteIcon.getIntrinsicWidth();  
 
        int xMarkLeft = itemView.getRight() - xMarkMargin - intrinsicWidth;  
        int xMarkRight = itemView.getRight() - xMarkMargin;  
        int xMarkTop = itemView.getTop() + (itemHeight - intrinsicHeight) / 2;  
        int xMarkBottom = xMarkTop + intrinsicHeight;  
 
        //Setting Swipe Icon  
        deleteIcon.setBounds(xMarkLeft, xMarkTop + 16, xMarkRight, xMarkBottom);  
        deleteIcon.draw(c);  
 
        //Setting Swipe Text  
        Paint paint = new Paint();  
        paint.setColor(Color.WHITE);  
        paint.setTextSize(48);  
        paint.setTextAlign(Paint.Align.CENTER);  
        c.drawText(getLeftSwipeLable(), xMarkLeft + 40, xMarkTop + 10, paint);  
 
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);  
    }  
 
    public String getLeftSwipeLable() {  
        return leftSwipeLable;  
    }  
 
    public void setLeftSwipeLable(String leftSwipeLable) {  
        this.leftSwipeLable = leftSwipeLable;  
    }  
 
    public int getLeftcolorCode() {  
        return leftcolorCode;  
    }  
 
    public void setLeftcolorCode(int leftcolorCode) {  
        this.leftcolorCode = leftcolorCode;  
    }  
}  


Buat kelas ItemViewHolder.java dan perluas RecyclerView.ViewHolder.

File : ItemViewHolder.java

package example.android.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);  
    }  
}  


Buat kelas adaptor MyAdapter.java yang memperluas kelas RecyclerView.Adapter dan menimpa metode onCreateViewHolder(), onBindViewHolder().

File : MyAdapter.java

package example.android.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);  
    }  
}  


Buat kelas MainActivityFragment.java dan perluas kelas Fragment. Di kelas ini, atur kelas adaptor MyAdapter.java dan kelas swipeutil.java utilitas.

File : 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.android.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>  


File : MainActivityFragment.java

package example.android.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));  
    }  
}  


File : 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> 


File : 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>  


File : 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 untuk Hapus RecyclerView item dengan UNDO


Berlangganan update artikel terbaru via email:

0 Response to "Android Swipe untuk Hapus RecyclerView item dengan UNDO"

Posting Komentar

Iklan Atas Artikel

Iklan Bawah Artikel