[技術博客] 通過ItemTouchHelper實現側滑刪除功能


通過ItemTouchHelper實現側滑刪除功能

一、效果

二、具體實現

demo中演示的這種左滑刪除的效果在手機APP中比較常用,安卓也為我們提供了專門的輔助類ItemTouchHelper來幫助我們實現這個功能。ItemTouchHelper是一個工具類,可實現側滑刪除和拖拽移動,使用這個工具類需要RecyclerView和Callback。同時根據需要重寫onMove和onSwiped方法。接下來就來講述ItemTouchHelper的使用方法。
具體代碼實現如下:

1、新建接口

從解耦的角度考慮,我們需要一個接口來實現Adapter和ItemTouchHelper之間涉及數據的操作,因為ItemTouchHelper在完成觸摸的各種動畫后,就要對Adapter的數據進行操作,比如側滑刪除操作。因此我們可以把數據操作的部分抽象成一個接口方法,讓ItemTouchHelper.Callback調用該方法即可。

public interface ItemTouchHelperAdapter {
    public void onItemDelete(int position);//用來刪除數據
    public void onItemRefresh(int position);//當用戶誤操作時用來恢復數據
}

2、在RecyclerView的Adapter類中實現接口中的兩個方法

這里為了讓大家看的清除把整個類都放上來了,其中只有下面兩個方法是接口中的,其他的方法是為了給RecyclerView傳遞數據,詳情可參考RecyclerView的使用方法。

public void onItemDelete(int position);
public void onItemRefresh(int position);

下面是demo中的我的收藏部分源碼

public class MyCollectionAdapter extends RecyclerView.Adapter<MyCollectionAdapter.innerHolder> implements ItemTouchHelperAdapter {
    private final ArrayList<ItemCollection> mData;
    private MyCollectionAdapter.OnItemClickListener clickListener;

    public MyCollectionAdapter(ArrayList<ItemCollection> data){
        this.mData = data;
    }

    @NonNull
    @Override
    //創建條目View
    public MyCollectionAdapter.innerHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = View.inflate(parent.getContext(), R.layout.user_item_collection,null);
        return new MyCollectionAdapter.innerHolder(view);
    }

    @Override
    //用來綁定holder,設置數據
    public void onBindViewHolder(@NonNull MyCollectionAdapter.innerHolder holder, int position) {
        holder.setData(mData.get(position),position);
    }

    @Override
    //返回Item的個數
    public int getItemCount() {
        if(mData != null){
            return mData.size();
        }
        return 0;
    }

    public void setOnItemClickListener(MyCollectionAdapter.OnItemClickListener listener) {
        //設置一個Item的監聽器
        clickListener = listener;
    }

    @Override
    public void onItemDelete(int position) {//刪除數據操作,即用戶點擊確定刪除時的邏輯
        ItemCollection del = mData.get(position);
        String url = "https://api.cnblogs.com/api/bookmarks/" + del.Id;
        DeleteApi delapi = new DeleteApi();
        @SuppressLint("HandlerLeak")
        final Handler handler = new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                if(msg.what == 1){
                    //刪除成功
                    System.out.println("成功刪除");
                }
            }
        };
        delapi.Delete(handler, url,1);//以上是API的調用刪除網絡數據部分
        mData.remove(position);//在本地ItemList中刪除要刪除的Item數據
        notifyItemRemoved(position);//提醒RecyclerView,使得后面的數據都向上移動一位
    }

    @Override
    public void onItemRefresh(int position) {//恢復數據,即用戶點擊取消時的邏輯
        notifyItemChanged(position);
    }

    public interface OnItemClickListener {//設置點擊操作
        void OnItemClick(int position);
    }

    public class innerHolder extends RecyclerView.ViewHolder {//用來設置list數據
        private TextView title;
        private TextView Abstract;
        private TextView time;
        private int mPosition;

        public innerHolder(@NonNull View itemView) {
            super(itemView);
            title = itemView.findViewById(R.id.item_Collection_blogtitle);
            Abstract = itemView.findViewById(R.id.item_Collection_abstract);
            time = itemView.findViewById(R.id.item_Collection_time);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (clickListener != null) {
                        clickListener.OnItemClick(mPosition);
                    }
                }
            });
        }
        public void setData(ItemCollection itembean,int position){
            this.mPosition = position;
            title.setText(itembean.title);
            Abstract.setText(itembean.Abstract);
            time.setText(itembean.time);
        }
    }
}

3、新建類繼承自ItemTouchHelper.Callback並重寫方法

從官方文檔我們知道,使用ItemTouchHelper需要一個Callback,該Callback是ItemTouchHelper.Callback的子類,所以我們需要新建一個類比如myItemTouchHelperCallBack繼承自ItemTouchHelper.Callback。我們可以重寫其數個方法來實現我們的需求。下面介紹demo中用到的方法。

public int getMovementFlags(RecyclerView, RecyclerView.ViewHolder)

該方法用於返回可以滑動的方向,比如說允許從右到左側滑,允許上下拖動等。
在本demo中,我們允許Item上下拖動以及從右向左滑,代碼如下:

public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        //允許上下拖動
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        //允許從右向左滑動
        int swipeFlags = ItemTouchHelper.LEFT;
        return makeMovementFlags(dragFlags,swipeFlags);
    }

public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)

當用戶拖動一個Item進行上下移動從舊的位置到新的位置的時候會調用該方法,在我們的實例中是禁止這種操作的。

public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        return false;
    }

public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)

當用戶左右滑動Item達到刪除條件時,會調用該方法,一般手指觸摸滑動的距離達到RecyclerView寬度的一半時,再松開手指,此時該Item會繼續向原先滑動方向滑過去並且調用onSwiped方法進行刪除,否則會反向滑回原來的位置。

public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        //onItemDelete接口里的方法
        showCoverDialog(viewHolder);
    }

private void showCoverDialog(final RecyclerView.ViewHolder viewHolder){//跳出提示窗口
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("提示");
        builder.setMessage(title);
        builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {//點擊確定時,刪除數據
                itemTouchHelperAdapter.onItemDelete(viewHolder.getAdapterPosition());
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {//點擊取消時恢復Item
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                itemTouchHelperAdapter.onItemRefresh(viewHolder.getAdapterPosition());
            }
        });
        builder.show();
    }

public boolean isLongPressDragEnabled()

該方法返回true時,表示支持長按拖動,即長按ItemView后才可以拖動,由於默認是true,這里要改為false

public boolean isLongPressDragEnabled() {
        //該方法返回值為true時,表示支持長按ItemView拖動
        return false;
    }

public boolean boolean isItemViewSwipeEnabled()

該方法返回true時,表示如果用戶觸摸並左右滑動了View,那么可以執行滑動刪除操作,即可以調用到onSwiped()方法。默認是true,為了看起來清除,我們也把這個方法寫上

public boolean isItemViewSwipeEnabled() {
        //該方法返回true時,表示如果用戶觸摸並且左滑了view,那么可以執行滑動刪除操作,就是可以調用onSwiped()方法
        return true;
    }

源代碼如下

public class myItemTouchHelperCallBack extends ItemTouchHelper.Callback{
    private ItemTouchHelperAdapter itemTouchHelperAdapter;
    private Context context;
    private String title;

    public myItemTouchHelperCallBack(ItemTouchHelperAdapter itemTouchHelperAdapter, Context context, String title) {
        this.itemTouchHelperAdapter = itemTouchHelperAdapter;
        this.context = context;
        this.title = title;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        //允許上下拖動
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        //允許從右向左滑動
        int swipeFlags = ItemTouchHelper.LEFT;
        return makeMovementFlags(dragFlags,swipeFlags);
    }

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        //onItemDelete接口里的方法
        showCoverDialog(viewHolder);
    }

    @Override
    public boolean isLongPressDragEnabled() {
        //該方法返回值為true時,表示支持長按ItemView拖動
        return false;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        //該方法返回true時,表示如果用戶觸摸並且左滑了view,那么可以執行滑動刪除操作,就是可以調用onSwiped()方法
        return true;
    }

    private void showCoverDialog(final RecyclerView.ViewHolder viewHolder){
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("提示");
        builder.setMessage(title);
        builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                itemTouchHelperAdapter.onItemDelete(viewHolder.getAdapterPosition());
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                itemTouchHelperAdapter.onItemRefresh(viewHolder.getAdapterPosition());
            }
        });
        builder.show();
    }
}

4、在RecycleView中添加ItemTouchHelper

ItemTouchHelper.Callback callback = new myItemTouchHelperCallBack(adapter,context,"確定刪除此這篇收藏嗎?");
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(myCollectionList);

自此我們就實現了左滑刪除功能。
整個工程的代碼在github上可以查看


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM