本文主要是介绍优雅地实现RecycleView的点击、拖动、和侧滑删除,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
优雅地实现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
处理即可。
@Overridepublic boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {mGestureDetector.onTouchEvent(e);return false;}@Overridepublic void onTouchEvent(RecyclerView rv, MotionEvent e) {mGestureDetector.onTouchEvent(e);}
mGestureDetector
捕捉到的事件都会交给ItemTouchHelperGestureListener
来处理:
class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {@Overridepublic 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;}@Overridepublic 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) {@Overridepublic void onItemClick(RecyclerView.ViewHolder holder, int position) {Toast.makeText(SampleRecycleViewActivity.this, "点击了:" + position, Toast.LENGTH_SHORT).show();}@Overridepublic 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
的实现如下:
//设置移动方式@Overridepublic 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
中进行数据集的更新:
//移动过程中调用@Overridepublic 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
方法。
//当长按的时候调用@Overridepublic void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {viewHolder.itemView.setBackgroundColor(Color.LTGRAY);}super.onSelectedChanged(viewHolder, actionState);}//当手指松开的时候调用@Overridepublic void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {super.clearView(recyclerView, viewHolder);viewHolder.itemView.setBackgroundResource(0);}
如果有需要对某些特定
item
不能拖动的话,可以重写isLongPressDragEnabled
返回false
,设置默认不可拖动。然后在前面实现的OnItemClickListener
的onLongPress
中对需要拖拽的item使用itemTouchHelper.startDrag(holder);
就可以拖动了
滑动删除
首先设置标志位:
//设置移动方式@Overridepublic 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
方法中进行数据集更新就可以了:
//侧滑过程中调用@Overridepublic void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {int position = viewHolder.getAdapterPosition();adapter.notifyItemRemoved(position);data.remove(position);}
整体效果如下:
这篇关于优雅地实现RecycleView的点击、拖动、和侧滑删除的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!