优雅地实现RecycleView的点击、拖动、和侧滑删除
来源:互联网 发布:python 网络拓扑图 编辑:程序博客网 时间:2024/06/05 13:34
优雅地实现RecycleView的点击、拖动、和侧滑删除
自从发布了RecycleView
之后,可以很方便的实现列表数据展示,同时只需要指定LayoutManager
就可以实现列表、瀑布流、表格布局的无缝切换。RecycleView
的所有东西都很美好,但是它没有提供像ListView
那样的单击item
的接口,都是通过对ViewHolder
实现OnclickListener
来实现单击事件。这里发现了一种更加优雅的方式,其本质是通过item
的onTouchEvent
事件来实现的。
点击事件
RecycleView
提供了一个接口叫做addOnItemTouchListener
用来为每个item
添加触摸事件,实现思路通过触摸手势监听,然后通过触摸坐标判断是哪个item
。
实现起来很简单:
1、定义一个OnItemClickListener
继承自RecycleView.OnItemTouchListener
,里面持有一个RecycleView
和一个GestureDetectorCompat
:
public abstract class OnItemClickListener implements RecyclerView.OnItemTouchListener { private GestureDetectorCompat mGestureDetector; private RecyclerView recyclerView; public RecycleItemClickListener(RecyclerView view) { this.recyclerView = view; mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(), ItemTouchHelperGestureListener()); }
然后OnItemTouchListener
有几个方法需要我们实现。onInterceptTouchEvent
、onTouchEvent
、onRequestDisallowInterceptTouchEvent
我们只需要在onInterceptTouchEvent
和onTouchEvent
中把事件交给mGestureDetector
处理即可。
@Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { mGestureDetector.onTouchEvent(e); return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { mGestureDetector.onTouchEvent(e); }
mGestureDetector
捕捉到的事件都会交给ItemTouchHelperGestureListener
来处理:
class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); if (child != null) { int position = recyclerView.indexOfChild(child); onItemClick(recyclerView.getChildViewHolder(child), position); } return true; } @Override public void onLongPress(MotionEvent e) { View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); if (child != null) { int position = recyclerView.indexOfChild(child); RecycleItemClickListener.this.onLongPress(recyclerView.getChildViewHolder(child), position); } } }
其中onItemClick
和onLongPress
是OnItemClickListener
提供给外部调用的回调。其声明如下:
public abstract void onItemClick(RecyclerView.ViewHolder holder, int position); public void onLongPress(RecyclerView.ViewHolder holder, int position) {}
onLongPress
在需要的时候可以重写。
RecycleView
使用时是这样的:
recyclerView.addOnItemTouchListener(new RecycleItemClickListener(recyclerView) { @Override public void onItemClick(RecyclerView.ViewHolder holder, int position) { Toast.makeText(SampleRecycleViewActivity.this, "点击了:" + position, Toast.LENGTH_SHORT).show(); } @Override public void onLongPress(RecyclerView.ViewHolder holder, int position) { } });
这样就实现了RecycleView
的onItemClickListener
了。
拖拽移动item
拖拽item的实现需要用到ItemTouchHelper
这个接口,这个接口是SDK提供的用于处理拖拽、侧滑删除等功能的。
使用这个东西的步骤非常简单:
- 实例化一个
ItemTouchHelper
- 关联
RecycleView
itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback()); itemTouchHelper.attachToRecyclerView(recyclerView);
就是这么简单。ItemTouchHelper
的构造方法需要一个CallBack
对象,这个CallBack
对象,需要实现几个方法:getMovementFlags
、onMove
、onSwiped
。
其中getMovementFlags
的实现如下:
//设置移动方式 @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { final int dragFlags; final int swipeFlags; if (recyclerView.getLayoutManager() instanceof GridLayoutManager) { dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; swipeFlags = 0; } else { dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; } return makeMovementFlags(dragFlags, swipeFlags); }
上面代码中,dragFlags
是用于拖拽的标志,swipeFlags
是滑动标记。上面代码意思是如果是网格布局,拖动方向为上下左右,否则只有上下方向。swipeFlags
是用于左右滑动的标志,这里暂且不说。
在设置了dragFlags
的时候,就会在长按item
的时候进入拖动模式,然后就会一直回调onMove
函数。我们可以在onMove
中进行数据集的更新:
//移动过程中调用 @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { int fromPosition = viewHolder.getAdapterPosition(); int toPosition = target.getAdapterPosition(); data.add(toPosition, data.remove(fromPosition)); adapter.notifyItemMoved(fromPosition, toPosition); return false; }
如果需要在拖拽过程中进行高亮背景切换,可以重写onSelectedChanged
和clearView
方法。
//当长按的时候调用 @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { viewHolder.itemView.setBackgroundColor(Color.LTGRAY); } super.onSelectedChanged(viewHolder, actionState); } //当手指松开的时候调用 @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); viewHolder.itemView.setBackgroundResource(0); }
如果有需要对某些特定
item
不能拖动的话,可以重写isLongPressDragEnabled
返回false
,设置默认不可拖动。然后在前面实现的OnItemClickListener
的onLongPress
中对需要拖拽的item使用itemTouchHelper.startDrag(holder);
就可以拖动了
滑动删除
首先设置标志位:
//设置移动方式 @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { final int dragFlags; final int swipeFlags; if (recyclerView.getLayoutManager() instanceof GridLayoutManager) { dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; swipeFlags = 0; } else { dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; } return makeMovementFlags(dragFlags, swipeFlags); }
START
和END
的标志位是指可以左右滑动。
其次在onSwipe
方法中进行数据集更新就可以了:
//侧滑过程中调用 @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { int position = viewHolder.getAdapterPosition(); adapter.notifyItemRemoved(position); data.remove(position); }
整体效果如下:
- 优雅地实现RecycleView的点击、拖动、和侧滑删除
- RecycleView实现侧滑和拖动
- RecycleView实现侧滑和拖动
- RecycleView如何设置点击拖动和定时拖动
- 数据库优雅地实现软删除
- 使用RecycleView实现侧滑删除
- RecycleView的优雅使用
- recycleView滑动删除,拖动排序
- recycleView滑动删除,拖动排序
- RecyclerView 实现侧滑删除和拖动排序
- SwipeMenuListView实现点击和侧滑删除
- 优雅地实现RecyclerView的复杂布局
- RecycleView如何实现item的点击事件
- RecycleView条目点击事件的实现方法
- android---RecycleView使用ItemTouchHelper实现拖拽和侧滑删除
- RecyclerView的侧滑删除和长按拖动
- 优雅地调查删除你微信的人
- recycleview左滑删除item实现
- Leetcode 347.Top K Frequent Elements
- android 图像动画常用的效果
- win7 快速启动栏 里的快捷方式存放路径
- android activity向fragment通信,获取fragment的三种方法
- redis的高级应用之一(Redis安全性\主从复制\事务处理)
- 优雅地实现RecycleView的点击、拖动、和侧滑删除
- 时间间隔: SystemClock.uptimeMillis与System.currentTimeMillis
- build your own lisp ch7 笔记
- 两个成员的类模板2
- Asp.net Web API 2 学习随手记 (Expression)
- ListView 条目多样式展示
- 查找的有关操作
- win10 64位缺少msvcp60d.dll和msvcrtd.dll文件
- redis 高级应用之二(Redis的持久化 和 消息的[pub/sub]发布和订阅)