通过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上可以查看

[技术博客] 通过ItemTouchHelper实现侧滑删除功能的更多相关文章

  1. 创建GitHub技术博客

    创建GitHub技术博客全攻略 githubio技术博客网站生成 说明: 首先,你需要注册一个 github 账号,最好取一个有意义的名字,比如姓名全拼,昵称全拼,如果被占用,可以加上有意义的数字.本 ...

  2. 创建GitHub技术博客全攻略【转】

    本文转载自:http://blog.csdn.net/renfufei/article/details/37725057/ 说明: 首先,你需要注册一个 github 账号,最好取一个有意义的名字,比 ...

  3. 技术人如何利用 github+Jekyll ,搭建一个独立免费的技术博客

    上次有人留言说,技术博客是程序员的标配,但据我所知绝大部分技术同学到现在仍然没有自己的技术博客.原因有很多,有的是懒的写,有的是怕写不好,还有的是一直想憋个大招,幻想做到完美再发出来,结果一直胎死腹中 ...

  4. [技术博客] 软工-Ruby on Rails 后端开发总结分享

    [技术博客] 软工-Ruby on Rails 后端开发总结分享 在这次软件编写中,我们的后端使用了Ruby on Rails (RoR)框架. Rails框架是用Ruby编写的.这意味着当我们为Ru ...

  5. 如何写出高质量的技术博客 这边文章出自http://www.jianshu.com/p/ae9ab21a5730 觉得不错直接拿过来了 好东西要大家分享嘛

        如何写出高质量的技术博客?答案是:如果你想,就一定能写出高质量的技术博客.看起来很唯心,但这就是事实.有足够愿力去做一件目标明确,有良好反馈系统的事情往往很简单.就是不停地训练,慢慢地,你自己 ...

  6. ******IT公司面试题汇总+优秀技术博客汇总

    滴滴面试题:滴滴打车数据库如何拆分 前端时间去滴滴面试,有一道题目是这样的,滴滴每天有100万的订单,如果让你去设计数据库,你会怎么去设计? 当时我的想法是根据用户id的最后一位对某个特殊的值取%操作 ...

  7. 转: BAT等研发团队的技术博客

    BAT 技术团队博客   1. 美团技术团队博客:  地址: http://tech.meituan.com/ 2. 腾讯社交用户体验设计(ISUX) 地址:http://isux.tencent.c ...

  8. 解决Eclipse中文乱码 - 技术博客 - 51CTO技术博客 http://hsj69106.blog.51cto.com/1017401/595598/

    解决Eclipse中文乱码 - 技术博客 - 51CTO技术博客  http://hsj69106.blog.51cto.com/1017401/595598/

  9. 欢迎访问我的最新个人技术博客http://zhangxuefei.top

    博客园已停止更新,欢迎访问我的最新个人技术博客http://zhangxuefei.top

随机推荐

  1. shell脚本中的多行注释

    shell 中注释的使用方法 1. 单行注释 单行注释最为常见,它是通过一个'#'来实现的.注意shell脚本的最开始部分"#!/bin/bash"的#号不是用来注释的. 2. 多 ...

  2. GridView控件使用

    增加显示列gridView.Columns.AddVisible("AgentName", "姓名");设置是否为只读gridView1.OptionsBeha ...

  3. Identity用户管理入门六(判断是否登录)

    目前用户管理的增删改查及登录功能已经全部实现,但存在一个问题,登录后要取消登录按钮显示退出按钮,未登录应该有注册按钮,现实现过程如下 一.Startup.cs中增加服务 app.UseAuthenti ...

  4. 分组概念&贪婪与懒惰

    分组概念&贪婪与懒惰 1.分组 2.贪婪和懒惰 3.懒惰 4.处理选项 5.实例:百度搜索结果页面源码中获取当前页的10个标题 5.1页面源码分析规律 5.2正则表达式,匹配出10个标题 这是 ...

  5. 分享一则Linux系统邮件提示 /usr/local/lib/libprocesshider.so > /etc/ld.so.preload 的中病毒解决方法

    ​ 系统环境:CentOS Linux release 7.6.1810 (AltArch)                   CPU架构:ARM            最近发现生产服务器CPU占用 ...

  6. MySQL索引、事务、存储引擎

    一.MySQL 索引 1.索引的概念 ●索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址(类似于C语言的链表通过指针指向数据记录的内存地址).●使用索引后可以不用扫描 ...

  7. selenium-ide-2.3.0 组件在foxfire45.0无法安装的问题

    楼主在安装selenium-ide组件时,尝试了下面两种方式都无法安装: 1.在forfire浏览器进行拖拽安装,页面无任何跳转.拖拽后回车安装,也没任何效果 2.附件组件-从文件安装添加组件,添加了 ...

  8. STM32F103C8T6使用SPI接口驱动WS2812b灯条

    之前一篇文章写了使用IO控制WS2812b操作原理,但是由于IO的输出比较慢,所以现在改用了硬件SPI控制WS2812b灯条 把SPI的mosi线接到ws2812b的数据线,SPI的速率可达十几Mbi ...

  9. 学习PHP中的任意精度扩展函数

    今天来学习的是关于数学方面的第一个扩展.对于数学操作来说,无非就是那些各种各样的数学运算,当然,整个程序软件的开发过程中,数学运算也是最基础最根本的东西之一.不管你是学得什么专业,到最后基本上都会要学 ...

  10. goto语法在PHP中的使用

    在C++.Java及很多语言中,都存在着一个神奇的语法,就是goto.顾名思义,它的使用是直接去到某个地方.从来代码的角度来说,也就是直接跳转到指定的地方.我们的PHP中也有这个功能,我们先来看看它是 ...