行业知识
【Android】RecyclerView拖动排序和侧滑删除功能实现
2026-11-05 17:25:52
来源:互联网转载
目录
- 简介
- 一、ItemTouchHandler 拖动排序和侧滑删除
- 二、SwipeDelMenuLayout 侧滑删除
- 总结
简介
ItemTouchHandler 是 Google 提供的一个工具类,主要针对 RecyclerView 的上下左右拖动事件进行处理,可以同时实现拖动排序和侧滑删除功能。涉及一些事件分发的知识,感兴趣可以去分析源码。
第三方SwipeDelMenuLayout,毫无耦合性,一个Item根布局搞定 item侧滑删除菜单。不依赖任何父布局,不是针对 RecyclerView、ListView,而是任意的 ViewGroup 里的 childView 都可以使用侧滑删除。
一、ItemTouchHandler 拖动排序和侧滑删除
效果展示:
- 先创建一个回调类:ItemTouchHelperCallBack
- context:上下文
- listData:列表数据
- adapter:对应适配器
- isDrag:是否可以拖拽
- isSwipe:是否可以侧滑
class ItemTouchHelperCallBack (val context: Context,val listData:List,val adapter:BaseQuickAdapter,val isDrag:Boolean=true,val isSwipe:Boolean=true): ItemTouchHelper.Callback()
- 实现方法(这些方法也可以设置接口在外部去实现)
- getMovementFlags:一个是dragFlags,表示拖动效果支持的方向,另一个是swipeFlags,表示侧滑效果支持的方向
override fun getMovementFlags( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder ): Int { var dragFlag = 0 if (recyclerView.layoutManager is GridLayoutManager) { dragFlag = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT } else if (recyclerView.layoutManager is LinearLayoutManager) { dragFlag = ItemTouchHelper.UP or ItemTouchHelper.DOWN } return makeMovementFlags(dragFlag, 0) }- onMove:当拖动开始时会回调此方法,通常将拖动的item与其他item交换位置,更新数据源
override fun onMove( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder ): Boolean { //absoluteAdapterPosition和layoutPosition相差不大: // layoutPosition相对于实际展示的布局:使用场景一般在notifyItemInserted之后, Layout不能马上获取到新的position, 布局还没更新时 // absoluteAdapterPosition相对于数据 val fromPosition = viewHolder.absoluteAdapterPosition //拿到当前拖拽到的item的viewHolder val toPosition = target.absoluteAdapterPosition if (fromPosition- onSwiped(可自行实现):当侧滑开始时调用,从数据源里面移除相应的数据
- onSelectedChanged :长按选中Item的时候开始调用,设置震动效果
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { //获取系统震动服务 震动70毫秒 val vib = context.getSystemService(AppCompatActivity.VIBRATOR_SERVICE) as Vibrator vib.vibrate(50) } super.onSelectedChanged(viewHolder, actionState) }- clearView:手指松开的时候调用,刷新数据
override fun clearView( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder ) { super.clearView(recyclerView, viewHolder) Handler().post(Runnable { adapter.notifyDataSetChanged(); //完成拖动后刷新适配器,这样拖动后删除就不会错乱 }) }- isLongPressDragEnabled、isItemViewSwipeEnabled
/** * 是否支持长按拖拽,默认为true,表示支持长按拖拽 * 对应长按移动位置功能 * 也可以返回false,手动调用startDrag()方法启动拖拽 */ override fun isLongPressDragEnabled(): Boolean { return isDrag } /** * 是否支持任意位置触摸事件发生时启用滑动操作,默认为true,表示支持滑动 * 对应滑动删除功能 * 也可以返回false,手动调用startSwipe()方法启动滑动 */ override fun isItemViewSwipeEnabled(): Boolean { return isSwipe }全部代码:
class ItemTouchHelperCallBack (val context: Context,val listData:List,val adapter:BaseQuickAdapter,val isDrag:Boolean=true,val isSwipe:Boolean=true): ItemTouchHelper.Callback() { //一个是dragFlags,表示拖动效果支持的方向,另一个是swipeFlags,表示侧滑效果支持的方向 override fun getMovementFlags( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder ): Int { var dragFlag = 0 if (recyclerView.layoutManager is GridLayoutManager) { dragFlag = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT } else if (recyclerView.layoutManager is LinearLayoutManager) { dragFlag = ItemTouchHelper.UP or ItemTouchHelper.DOWN } return makeMovementFlags(dragFlag, 0) } //当拖动效果已经产生了,会回调此方法,通常会更新数据源 override fun onMove( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder ): Boolean { //absoluteAdapterPosition和layoutPosition相差不大: // layoutPosition相对于实际展示的布局:使用场景一般在notifyItemInserted之后, Layout不能马上获取到新的position, 布局还没更新时 // absoluteAdapterPosition相对于数据 val fromPosition = viewHolder.absoluteAdapterPosition //拿到当前拖拽到的item的viewHolder val toPosition = target.absoluteAdapterPosition if (fromPosition- 使用
先设置isDrag为false,指定某个控件再去启动拖动
private val itemTouchHelper by lazy { //数据listData会改变 ItemTouchHelper( ItemTouchHelperCallBack( context = this, listData = itemData, adapter = itemAdapter, isDrag = false ) ) }//与recyclerView控件绑定itemTouchHelper.attachToRecyclerView(rv_add_item)//指定item里面的某个控件长按才能拖动adapter.setLongClickInterface(object :SetShowTabAdapter.LongClickInterface{ override fun onDrag(holder: BaseViewHolder) { itemTouchHelper.startDrag(holder) } })二、SwipeDelMenuLayout 侧滑删除
效果展示:
- 导入依赖
implementation 'com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0'
- xml设置
在适配器的item布局中,给需要滑动删除那个控件外层添加一个 SwipeMenuLayout 标签包裹住控件和一个删除按钮,让控件宽度铺满屏幕
- 使用
使用非常简单,只需要在适配器配置相应的点击事件即可
holder.getView(R.id.btn_delete).setOnClickListener { if(holder.absoluteAdapterPosition in 0 until itemCount){ list.removeAt(holder.absoluteAdapterPosition) //移除数据 notifyItemRemoved(holder.absoluteAdapterPosition) //刷新adapter } }总结
实现这两个功能有很多方法,都是比较简单的。
很长时间没更新了,之前去备考了,希望能有个好结果吧
- isLongPressDragEnabled、isItemViewSwipeEnabled
- clearView:手指松开的时候调用,刷新数据
- onMove:当拖动开始时会回调此方法,通常将拖动的item与其他item交换位置,更新数据源
上一篇:西子服务器怎么查看故障?
下一篇:Web 服务器的搭建