Android一步步带你在RecyclerView上面实现"拖放"和"滑动删除"功能

发布时间 - 2026-01-11 00:18:53    点击率:

先给大家展示下大概效果图:

Android上面有许多的教程, 库和示例, 在RecyclerView上面实现"拖放"和"滑动删除"功能. 尽管有更新, 更好的方法可用, 但是大多数人依然使用旧的View.OnDragListener和Roman Nurik的SwipeToDismiss方式. 除了经常使用GestureDetector和onInterceptTouchEvent之外, 几乎很少有人使用新的API, 要不然的话, 实现就复杂. 事实上真的有十分简单的方式在RecyclerView上面添加这两个功能. 它只要求一个类, 而且这个类已经是Android支持包的一部分.

ItemTouchHelper

ItemTouchHelper是一个强大的通用程序, 在RecyclerView上面添加"拖放"和"滑动删除"时, 你所需要做的所有事情, 它都会负责处理. 它是RecyclerView.ItemDecoration的子类, 这意味着它可以轻易地添加到任何已经存在的LayoutManager和Adapter上面! 它不会影响添加到item上的动画, 并且支持类别严格的"拖", 以及"放"时的动画, 还可以支持更多.

准备:

首先, 我们所需要的是添加RecyclerView的依赖:

 compile 'com.android.support:recyclerview-v7:25.3.0'

使用ItemTouchHelper和ItemTouchHelper.Callback:

为了使用ItemTouchHelper, 你将创建一个ItemTouchHelper.Callback, 这是一个接口, 允许你监听"move"和"swipe"事件, 而且你可以通过Callback来控件已选中view的状态, 并且可以改变该view的默认动画. 如果只是想要一个基础实现, 你可以使用SimpleCallback这个帮助类, 但是为了学习Callback的工作原理, 我们将会自己实现一个.

为了激活基本的"拖放"和"滑动删除", 我们必须覆盖的主要方法是:

getMovementFlags(RecyclerView, ViewHolder)
onMove(RecyclerView, ViewHolder, ViewHolder)
onSwiped(ViewHolder, int)

我们也要使用这两个方法:

isLongPressDragEnabled()
isItemViewSwipeEnabled()

我们一个一个地看一下:

@Override
public int getMovementFlags(RecyclerView recyclerView, 
  RecyclerView.ViewHolder viewHolder) {
 int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
 int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
 return makeMovementFlags(dragFlags, swipeFlags);
}

ItemTouchHelper允许你轻易地决定事件的方向.你必须实现getMovementFlags(RecyclerView, RecyclerView.ViewHolder)方法来指明"拖"和"滑动"所支持的方向, 并且使用ItemTouchHelper.makeMovementFlags(int, int)来构建返回标签. 在此我们在两个不同的方向激活"拖"和"滑动".

@Override
public boolean isLongPressDragEnabled() {
 return true;
}

ItemTouchHelper能够用来实现"没有滑动的拖动"或者"没有拖动的滑动", 所以你必须精确地指明想要支持的动作. 如果你想要在RecyclerView的item上支持"长按启动拖放"事件, 你就必须实现isLongPressDragEnabled()返回true. 此外, ItemTouchHelper.startDrag(RecyclerView.ViewHolder)可以从"操作"中启动"拖放", 这一点会在之后详述.

@Override
public boolean isItemViewSwipeEnabled() {
 return true;
}

要想要view内部的任意触摸事件都可以启动"滑动"动作, 就简单地在isItemViewSwipeEnabled()返回true. 此外, ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)能够手动地启动"滑动"事件.

然后, onMove()和onSwiped()方法需要实现, 来通知负责更新基础数据的东西. 所以, 首先, 我们要创建一个接口, 以允许我们传递"拖放"和"滑动删除"事件的回调.

public interface ItemTouchHelperAdapter {
 void onItemMove(int fromPosition, int toPosition);
 void onItemDismiss(int position);
}

从当前示例来讲, 要实现这些的最简单的方式, 是将我们的RecyclerView.Adapter实现这个接口:

public class RecyclerListAdapter extends 
  RecyclerView.Adapter<ItemViewHolder> 
  implements ItemTouchHelperAdapter {
// ... code from gist
@Override
public void onItemDismiss(int position) {
 mItems.remove(position);
 notifyItemRemoved(position);
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
 if (fromPosition < toPosition) {
  for (int i = fromPosition; i < toPosition; i++) {
   Collections.swap(mItems, i, i + 1);
  }
 } else {
  for (int i = fromPosition; i > toPosition; i--) {
   Collections.swap(mItems, i, i - 1);
  }
 }
 notifyItemMoved(fromPosition, toPosition);
 return true;
}

调用notifyItemRemoved(int)和notifyItemMoved(int, int)是非常重要的, 由此, Adapter会更新数据. 请注意, 这也很重要, 我们改变item的position是在每一次view被切换到新的index, 而不是在"放"事件之后.

现在我们回来构建SimpleItemTouchHelperCallback, 因为我们依然必须覆盖onMove()和onSwiped()方法. 首先, 为Adapter添加构建器和变量:

private final ItemTouchHelperAdapter mAdapter;
public SimpleItemTouchHelperCallback(
  ItemTouchHelperAdapter adapter) {
 mAdapter = adapter;
}

然后覆盖剩下的事件并通知Adapter:

@Override
public boolean onMove(RecyclerView recyclerView, 
  RecyclerView.ViewHolder viewHolder, 
  RecyclerView.ViewHolder target) {
 mAdapter.onItemMove(viewHolder.getAdapterPosition(), 
   target.getAdapterPosition());
 return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, 
  int direction) {
 mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}

这个Callback应该看起来像这样:

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
 private final ItemTouchHelperAdapter mAdapter;
 public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
  mAdapter = adapter;
 }
 @Override
 public boolean isLongPressDragEnabled() {
  return true;
 }
 @Override
 public boolean isItemViewSwipeEnabled() {
  return true;
 }
 @Override
 public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {
  int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
  int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
  return makeMovementFlags(dragFlags, swipeFlags);
 }
 @Override
 public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, 
   ViewHolder target) {
  mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
  return true;
 }
 @Override
 public void onSwiped(ViewHolder viewHolder, int direction) {
  mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
 }
}

当Callback准备好之后, 我们创建ItemTouchHelper并调用attachToRecyclerView(RecyclerView)方法:

ItemTouchHelper.Callback callback = 
 new SimpleItemTouchHelperCallback(adapter);
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(recyclerView);

当你运行的时候, 结果应该看起来像这样:

总结

这是一个ItemTouchHelper极简单的实现. 但是我们应该清楚, 在RecyclerView上面实现基本的"拖放"和"滑动删除", 使用第三方和库是完全没有必要的.

示例代码请点击这里.

以上所述是小编给大家介绍的Android一步步带你在RecyclerView上面实现"拖放"和"滑动删除"功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


# recyclerview  # 滑动  # 拖放  # android  # Android开发在RecyclerView上面实现"拖放"和"滑动删除"-2  # android RecyclerView侧滑菜单  # 滑动删除  # 长按拖拽  # 下拉刷新上拉加载  # android RecyclerView实现条目Item拖拽排序与滑动删除  # Android中RecyclerView实现滑动删除与拖拽功能  # Android 滑动监听RecyclerView线性流+左右划删除+上下移动  # Android RecyclerView滑动删除和拖动排序  # Android RecyclerView实现滑动删除  # 是在  # 你可以  # 在此  # 这是一个  # 这两个  # 拖动  # 你必须  # 创建一个  # 小编  # 的是  # 是一个  # 还可以  # 你就  # 将会  # 子类  # 也要  # 你在  # 当你  # 会在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  Laravel如何保护应用免受CSRF攻击?(原理和示例)  Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  轻松掌握MySQL函数中的last_insert_id()  香港服务器租用每月最低只需15元?  php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】  为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】  猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  HTML 中动态设置元素 name 属性的正确语法详解  网站建设要注意的标准 促进网站用户好感度!  Laravel的.env文件有什么用_Laravel环境变量配置与管理详解  Laravel如何使用Telescope进行调试?(安装和使用教程)  如何在IIS中配置站点IP、端口及主机头?  Laravel怎么使用artisan命令缓存配置和视图  PHP正则匹配日期和时间(时间戳转换)的实例代码  *服务器网站为何频现安全漏洞?  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  使用PHP下载CSS文件中的所有图片【几行代码即可实现】  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  中山网站推广排名,中山信息港登录入口?  详解Android中Activity的四大启动模式实验简述  悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】  Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?  ,在苏州找工作,上哪个网站比较好?  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  Linux后台任务运行方法_nohup与&使用技巧【技巧】  网站制作大概多少钱一个,做一个平台网站大概多少钱?  php做exe能调用系统命令吗_执行cmd指令实现方式【详解】  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  大型企业网站制作流程,做网站需要注册公司吗?  php json中文编码为null的解决办法  Python进程池调度策略_任务分发说明【指导】  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  php在windows下怎么调试_phpwindows环境调试操作说明【操作】  网站优化排名时,需要考虑哪些问题呢?  Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  免费网站制作appp,免费制作app哪个平台好?  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】