关于RecycleView你需要知道的之「侧滑删除与拖拽排序」

2017-09-13 10:44:05来源:http://flyou.ren/2017/09/05/关于RecycleView你需要知道的之「侧滑删除与拖拽排序」/作者:flyou人点击

分享

在上一篇我们了解了下Recycle View的装饰器,今天我们来看下RecycleView的侧滑删除与拖拽排序。


在ListView中实现拖拽排序,需要配合WindowManager来实现ItemView的浮动效果,需要自己实现拖动效果,越界处理等,很是麻烦。


但是,RecycleView中已经默认为拖拽提供了支持.


extents RecyclerView.ItemDecoration


implementsRecyclerView.OnChildAttachStateChangeListener


java.lang.Object


↳ android.support.v7.widget.RecyclerView.ItemDecoration


↳ android.support.v7.widget.helper.ItemTouchHelper


ItemTouchHelper


This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.


这是一个实用工具类,用于添加滑动以关闭并拖放到RecyclerView的支持。


从官方文档可以看出,ItemTouchHelper继承于我们上一节讲到的ItemDecoration并且实现了OnChildAttachStateChangeListener接口,主要用户处理滑动和拖拽效果。


2. ItemTouchHelper

初始化ItemTouchelper非常简单,只需要传入一个指定的CallBack就行了


ItemTouchHelper(ItemTouchHelper.Callback callback)


设置的方法也很简单


ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback());
itemTouchHelper.attachToRecyclerView(mRecyclerView);

只有两步就可以完成ItemTouchHelper与RecycleView的绑定,接来下我们需要重点看下Callback


自定义一个类实现 ItemTouchHelper.Callback 接口,实现以下方法:


//通过返回值来设置是否处理某次拖曳或者滑动事件
public abstract int getMovementFlags(RecyclerView recyclerView,
ViewHolder viewHolder);
//当长按并进入拖曳状态时,拖曳的过程中不断的回调此方法,返回值为是否处理事件
public abstract boolean onMove(RecyclerView recyclerView,
ViewHolder viewHolder, ViewHolder target);
//滑动删除的回调
public abstract void onSwiped(ViewHolder viewHolder, int direction);

getMovementFlags需要你根据自己LayoutManager的类型和ItemView的位置来指定自己是否可以滑动,是否可以拖拽,拖拽的方向,滑动的方向。


需要调用makeMovementFlags(dragFlags, swipeFlags)传入指定的Flags


Flags:


DOWN:支持往下拖拽或者滑动


UP:支持往上拖拽或者滑动


LEFT:支持往左拖拽或者滑动


RIGHT:支持往右拖拽或者滑动


START:由LayoutManager的方向决定左或者右


END:由LayoutManager的方向决定左或者右


如果传入0则代表不支持拖拽或者侧滑事件监听


3. 侧滑删除

首先我们需要实现getMovementFlags方法并且调用ItemTouchHelper中的静态方法,makeMovementFlags(dragFlags, swipeFlags)来设置ItemView可以接受滑动事件的方向。


@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = 0;
int swipeFlags =ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}

我们先设置dragFlags等于0,来禁止拖拽,设置swipeFlags为支持左右滑动。


为了实现滑动删除我们还要实现onSwiped方法,来处理删除操作


@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int adapterPosition = viewHolder.getAdapterPosition();
recyclerAdapter.notifyItemRemoved(adapterPosition);
dataList.remove(adapterPosition);
}

从上面代码可以看出,我们获取滑动ItemView位置移除ItemView并更新RecycleView。



上面仅仅实现了LinearLayoutManager竖向排列的效果,如果要实现LinearLayoutManager横向布局的效果只需要改变


swipeFlags 设置为 ItemTouchHelper.UP|ItemTouchHelper.BOTTOM即可。也可以设置swipeFlags为一个方向也是可以的,大家可以根据自己的需要进行设定。的滑动删除效果,和上面也是一样的.


4. Item拖拽

在上面我们在getMovementFlags把dragFlags设置为0,现在我们为了实现拖拽效果他当然不能为零了啊。


当然,Flag的几种类型还是和上面讲到的一样的,只不过LinearLayoutManager只能同时支持左右或者上下两个方向进行拖拽而GridLayoutManager和StaggeredGridLayoutManager可以同时支持上下左右4个方向的拖拽。


@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int swipeFlags = 0;
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
if (((LinearLayoutManager) recyclerView.getLayoutManager()).getOrientation() == LinearLayoutManager.VERTICAL) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
} else {
int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
}
return makeMovementFlags(dragFlags, swipeFlags);
} else
{
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}

在这里如果LayoutManager为竖向LinearLayoutManager则设置为允许上下拖拽,如果是横向LinearLayoutManager


则设置为允许左右拖拽,如果为GridLayoutManager和StaggeredGridLayoutManager则设置为上下左右都可以拖拽


然后我们需要实现onMove方法


@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder
viewHolder, RecyclerView.ViewHolder target) {
//拖动的 item 的下标
int fromPosition = viewHolder.getAdapterPosition();
//目标 item 的下标
//目标 item 就是当拖曳过程中,不断和拖动的 item 做位置交换的条目。
int toPosition = target.getAdapterPosition();
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(dataList, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(dataList, i, i - 1);
}
}
recyclerAdapter.notifyItemMoved(fromPosition, toPosition);
return true;
}

我们通过ViewHolder获得选择的Item和目标Item,然后判断两个Item的顺序,交换两个Item之间所有Item的位置,最后更新recycleView


运行下看下效果:



看下GridLayoutManager的效果



5. 反馈与修饰

当然,上面已经实现了简单的侧滑和拖拽的功能,但是我们在可以开始侧滑和拖动的时候我们是不知道的,我们需要在可以开始拖动时给用户加点反馈(动画,震动,形变等等)


在这里需要说一下onSelectedChanged()和clearView()方法。


当item开始滑动或者可以被退拽是回调onSelectedChanged()


当滑动停止或者拖拽结束时回调clearView()


那么我们完全可以在onSelectedChanged()给Item加一些“特效”,然后在clearView()清除特效,下面我们演示下在拖拽时改变ItemView的背景颜色和大小,开始拖拽时震动反馈。


@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
//给被拖曳的 item 设置一个深颜色背景
viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
viewHolder.itemView.setScaleX(0.9f);
viewHolder.itemView.setScaleY(0.9f);
mVibrator.vibrate(20);//震动
}
super.onSelectedChanged(viewHolder, actionState);
}

在clearView()还原ItemView状态


@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
viewHolder.itemView.setBackgroundColor(Color.WHITE);
viewHolder.itemView.setScaleX(1.0f);
viewHolder.itemView.setScaleY(1.0f);
super.clearView(recyclerView, viewHolder);
}


当然,你也可以给ItemView上设置动画,当然了那是你的事。。。





是不是觉得,实现ItemView拖拽和侧滑很简单,但是onSwiped()和onMove()的应用不仅仅与此,可以实现很多炫酷的东西,到底是啥,请看下回分解


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台