Recyclerview条目可拖拽可侧滑删除实战详解
2017-04-23 10:13
387 查看
先看效果图
![](https://img-blog.csdn.net/20170423084857607?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ1MDEyNzQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
要实现这种效果,Android提供的有相关Api:ItemTouchHelper, 它是继承ItemDecoration的, 它内部有一个静态的抽象类
首先我们需要准备一个recyclerview的列表数据
[下面开始正文]
我们需要重写ItemTouchHelper.Callback这个抽个抽象类,并需要重写三个方法:
getMovementFlags : 主要通过这个方法,我们能拿到一个方向
onMove:拖动时回调这个函数
onSwiped : 侧滑回调这个函数
问题来了我们怎么知道它根据什么知道长按拖动还是侧滑删除呢?
所以我们还需要两个辅助方法用来判断是拖动还是侧滑:isLongPressDragEnabled和isItemViewSwipeEnabled()
在这个ItemTouchHelper.Callback静态抽象内部类中有这两个方法
ItemTouchHelper.Callback与Adapter进行通信
目的是要adapter时刻知道列表发生了变化,以便及时刷新ui界面
这里我们定义一个接口进行通信,我们需要当ui界面发生拖动和侧滑事件后,把位置的变化信息传递给接口。然后adapter实现这个接口,就可以从里面获取位置信息了,这样就可以及时刷新ui界面了!
看完整WolfItemTouchHelperCallback.java
看完整WolfRecAdapter.java
最后在activity中的使用
到这里已经实现了可拖动可侧滑删除的功能了!
我们通过Log进一步分析下
我们打开app,不做任何操作,在当前界面显示的条目:
![](https://img-blog.csdn.net/20170423093501757?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ1MDEyNzQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
拖拽时:把第二个条目(position1)拖到第一个条目的位置(position0)
![](https://img-blog.csdn.net/20170423095032638?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ1MDEyNzQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
我们可以发现当我们触目条目时会调用getMovementFlags,确定是长按拖动时会依次调用:isLongPressDragEnabled-getMovementFlags-onMove-onItemMove(自定义的接口)
侧滑删除时:
![](https://img-blog.csdn.net/20170423100016309?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ1MDEyNzQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
之所以多次调用isItemViewSwipeEnabled是因为,只要我们滑动列表就会多次调用,我们点击时很难准确的点到一个点。getMovementFlags-onSwiped-onItemDimss。position也会发生变化,因为删除一个后面的肯定要补充一个位置。
通过这些log我们很明确的看到他的调用流程了!
Activity-WolfItemTouchHelperCallback-WolfRecAdapter刷新界面
demo免费下载:本人使用的as是2.3版本的
http://download.csdn.net/detail/qq_34501274/9822706
要实现这种效果,Android提供的有相关Api:ItemTouchHelper, 它是继承ItemDecoration的, 它内部有一个静态的抽象类
public abstract static class Callback
首先我们需要准备一个recyclerview的列表数据
[下面开始正文]
我们需要重写ItemTouchHelper.Callback这个抽个抽象类,并需要重写三个方法:
getMovementFlags : 主要通过这个方法,我们能拿到一个方向
onMove:拖动时回调这个函数
onSwiped : 侧滑回调这个函数
public class WolfItemTouchHelperCallback extends Callback{ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { return 0; } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { } }
问题来了我们怎么知道它根据什么知道长按拖动还是侧滑删除呢?
所以我们还需要两个辅助方法用来判断是拖动还是侧滑:isLongPressDragEnabled和isItemViewSwipeEnabled()
在这个ItemTouchHelper.Callback静态抽象内部类中有这两个方法
/** * 可拖动返回true * */ @Override public boolean isLongPressDragEnabled() { return true; } /** * 可侧滑返回true * */ @Override public boolean isItemViewSwipeEnabled() { return true; }
ItemTouchHelper.Callback与Adapter进行通信
目的是要adapter时刻知道列表发生了变化,以便及时刷新ui界面
这里我们定义一个接口进行通信,我们需要当ui界面发生拖动和侧滑事件后,把位置的变化信息传递给接口。然后adapter实现这个接口,就可以从里面获取位置信息了,这样就可以及时刷新ui界面了!
//定义的接口 public interface ItemHelper { //拖动 void onItemMove(int frompos,int topos); //侧滑 void onItemDimss(int topos); }
看完整WolfItemTouchHelperCallback.java
public class WolfItemTouchHelperCallback extends ItemTouchHelper.Callback { /** * 第一步重写这三个方法 * getMovementFlags * onMove * onSwiped * 第二步重写这三个方法后我们还需要两个帮助函数 * isLongPressDragEnabled 和 * isItemViewSwipeEnabled * 第三步自定义接口作为WolfItemTouchHelperCallback和Adapter通信的桥梁,在构造方法中声明这个接口 * * */ private ItemHelper itemHelper; public WolfItemTouchHelperCallback(ItemHelper itemHelper){ this.itemHelper=itemHelper; } /** * 获取一个方向 * */ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //up down 既能向上拖拽也能向下拖拽 int up_down_drags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipes = ItemTouchHelper.START | ItemTouchHelper.END; Log.e("getMovementFlags","getMovementFlags"); return makeMovementFlags(up_down_drags,swipes); } /** * 拖动时调用 * */ @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { /** * 这个函数在拖动时调用 * 我们在拖动时,需要把拖动item的起始position,和要拖到到的位置的position,通知给adapter,让其刷新view * 我们可以通过自定义接口来传递数据 * */ int adapterFrom_Position = viewHolder.getAdapterPosition(); int adapterTo_Position = target.getAdapterPosition(); Log.e("onMove","onMove"); //这里把位置信息传递给接口了 itemHelper.onItemMove(adapterFrom_Position,adapterTo_Position); return true; } /** * 侧滑时调用 * */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { int adapterPosition = viewHolder.getAdapterPosition(); Log.e("onSwiped","onSwiped"); itemHelper.onItemDimss(adapterPosition); } /** * 可拖动返回true * */ @Override public boolean isLongPressDragEnabled() { return true; } /** * 可侧滑返回true * */ @Override public boolean isItemViewSwipeEnabled() { return true; } }
看完整WolfRecAdapter.java
public class WolfRecAdapter extends RecyclerView.Adapter<WolfRecAdapter.ViewHolder> implements ItemHelper{ public Context mCpntext; public List mList; private final LayoutInflater inflater; public WolfRecAdapter(Context mCpntext, List mList){ thi c983 s.mCpntext=mCpntext; this.mList=mList; inflater = LayoutInflater.from(mCpntext); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.item, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { Log.e("position","position"+position); holder.tv.setText(mList.get(position)+""); } @Override public int getItemCount() { return mList.size(); } /** * 拖拽时 * */ @Override public void onItemMove(int frompos, int topos) { Object remove = mList.remove(frompos); mList.add(topos > frompos ? topos - 1 : topos, remove); Log.e("onItemMove","onItemMove"); //刷新view notifyItemMoved(frompos,topos); } /** * 侧滑 * */ @Override public void onItemDimss(int topos) { mList.remove(topos); Log.e("onItemDimss","onItemDimss"); //移除 notifyItemRemoved(topos); } public class ViewHolder extends RecyclerView.ViewHolder{ private final TextView tv; public ViewHolder(View itemView) { super(itemView); tv = (TextView) itemView.findViewById(R.id.tv); } } }
最后在activity中的使用
//在设置玩适配器后可以这样写 //把adapter自定义的WolfItemTouchHelperCallback ItemTouchHelper.Callback callback = new WolfItemTouchHelperCallback(wolfRecAdapter); //把自定义的WolfItemTouchHelperCallback 传入到ItemTouchHelper ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback); itemTouchHelper.attachToRecyclerView(recyclerView);
到这里已经实现了可拖动可侧滑删除的功能了!
我们通过Log进一步分析下
我们打开app,不做任何操作,在当前界面显示的条目:
拖拽时:把第二个条目(position1)拖到第一个条目的位置(position0)
我们可以发现当我们触目条目时会调用getMovementFlags,确定是长按拖动时会依次调用:isLongPressDragEnabled-getMovementFlags-onMove-onItemMove(自定义的接口)
侧滑删除时:
之所以多次调用isItemViewSwipeEnabled是因为,只要我们滑动列表就会多次调用,我们点击时很难准确的点到一个点。getMovementFlags-onSwiped-onItemDimss。position也会发生变化,因为删除一个后面的肯定要补充一个位置。
通过这些log我们很明确的看到他的调用流程了!
Activity-WolfItemTouchHelperCallback-WolfRecAdapter刷新界面
demo免费下载:本人使用的as是2.3版本的
http://download.csdn.net/detail/qq_34501274/9822706
相关文章推荐
- RecyclerView进阶:使用ItemTouchHelper实现拖拽和侧滑删除
- RecyclerView进阶:使用ItemTouchHelper实现拖拽和侧滑删除效果
- RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载
- RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载
- android的RecyclerView实现拖拽排序和侧滑删除示例
- Android基础——RecyclerView拖拽排序侧滑删除
- RecyclerView实现条目Item拖拽排序与滑动删除
- Android实现RecyclerView侧滑删除和长按拖拽
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- 最强RecyclerView,Item侧滑菜单,长按拖拽Item,滑动删除Item。可以和任何下拉刷新框架结合使用
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- 详解RecyclerView+BGARefreshLayout实现自定义下拉刷新、上拉加载和侧滑删除效果
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- RecyclerView ItemTouchHelper实现拖拽,侧滑删除
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- RecyclerView实现条目Item拖拽排序与滑动删除
- Android LRecyclerView实现Item侧滑菜单、长按拖拽Item、滑动删除Item等功能
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能