Recyclerview条目可拖拽可侧滑删除实战详解
先看效果图
要实现这种效果,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){ this.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自定义的WolfItemTouchHelperCallbackItemTouchHelper.Callback callback = new WolfItemTouchHelperCallback(wolfRecAdapter);//把自定义的WolfItemTouchHelperCallback 传入到ItemTouchHelperItemTouchHelper 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
更多相关文章
- Android中进行https请求信任证书问题(效率解决,小白适用)
- Android之appWidget按钮事件
- Android框架ButterKnife的使用详解,butterknife8.x.x版本的使用方
- Android中的TextView 、EditText、Activity、Intent实例小计算器
- Android实现数据存储技术 de 五种方式
- android实现耳机插入和拔出状态检测
- Android(安卓)handler使用方法
- [Android]ActivityUnitTestCase解释
- Android中startActivity的使用----请求码与结果码的意义