RecyclerView实现滑动和拖拽功能(带小例子)
来源:互联网 发布:本地连接服务器数据库 编辑:程序博客网 时间:2024/05/14 09:54
前言: RecyclerView相对于ListView实现拖拽和滑动的效果要容易很多,今天写一个小程序,在上一篇文章 RecyclerView+CardView使用总结(带小例子) 基础上实现RecyclerView条目的上下拖拽和滑动删除,效果图如下:
第一步:设置拖动和滑动的回掉,让recyclerView和回调处理关联起来 主要代码如下:
mRecyclerView = (RecyclerView) mView.findViewById(R.id.hot_fragment_rcv);/*1,设置管理器*/mRecyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));/*2,设置适配器*/initListData();mAdapter = new HotFgListStrAdapter(mDatas);mRecyclerView.setAdapter(mAdapter);/**设置拖动和滑动的回调*/ItemTouchHelper.Callback callback = new RecycleItemTouchHelper(mAdapter);ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);itemTouchHelper.attachToRecyclerView(mRecyclerView);/*3,添加item的添加和移除动画, 这里我们使用默认的*/mRecyclerView.setItemAnimator(new DefaultItemAnimator());/*4,添加分割线,自定义分割线*/mRecyclerView.addItemDecoration(new HotFgItemDecoration());
第二步,实现拖动和滑动的方式,怎么拖动和滑动,向哪个方向拖动和滑动
ItemTouchHelper.Callback是谷歌提供的强大的工具类,处理RecyclerView拖动和滑动的实现,并且可以实现我们自己定义的动画和定制的效果。RecycleItemTouchHelper是我们继承ItemTouchHelper.Callback实现的。对于实现那几个函数,函数的作用,我在代码中做了注释,代码如下:
RecycleItemTouchHelper.java
public class RecycleItemTouchHelper extends ItemTouchHelper.Callback { private final ItemTouchHelperCallback helperCallback; public RecycleItemTouchHelper(ItemTouchHelperCallback helperCallback) { this.helperCallback = helperCallback; } /** * 该方法返回一个整数,用来指定拖拽和滑动在哪个方向是可以的。 * @param recyclerView * @param viewHolder * @return */ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { /** * makeMovementFlags(int dargFlags, int swipeFlags) * 该方法第一个参数指定拖动,第二个参数自定滑动。参数选择有六个如下: * ItemTouchHelper.UP 滑动拖拽方向向上 * ItemTouchHelper.DOWN 向下 * ItemTouchHelper.LEFT 向左 * ItemTouchHelper.RIGHT 向右 * ItemTouchHelper.START 依赖布局方向的水平开始方法(右向左) * ItemTouchHelper.END 依赖布局方向的水平结束方向(左向右) */ //本次设置结果为 支持上下拖拽,向右滑动 int flag = makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN, ItemTouchHelper.END); return flag; } /** * 该方法是拖拽的回掉 * @param recyclerView * @param viewHolder 表示拖动的item * @param target 表示拖动的目标位置的item * @return 如果item切换的位置返回true, 否则返回false */ @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { helperCallback.onMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } /** * 该方法为item滑动的回掉 * @param viewHolder 表示滑动的item * @param direction 表示滑动的方向 */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { helperCallback.onItemDelete(viewHolder.getAdapterPosition()); } //*********上面的三个方法是必须实现的*********下面三个方法可选择实现 /** * item是否支持长按拖动,true支持,false不支持 * @return */ @Override public boolean isLongPressDragEnabled() { return super.isLongPressDragEnabled(); } /** * item是否支持滑动,true支持,false不支持 * @return */ @Override public boolean isItemViewSwipeEnabled() { return super.isItemViewSwipeEnabled(); } /** * 移动过程中绘制item * @param c * @param recyclerView * @param viewHolder * @param dX 表示x轴移动距离 * @param dY 表示y轴移动距离 * @param actionState 当前item的状态 * @param isCurrentlyActive 如果当前用户在操作则为true,否则为false */ @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); }}
方法说明,我在注释中已经解释,这里就不再解释了,注意: 如果实现拖动或者滑动必须将上面的是否支持拖动isLongPressDragEnabled()和是否支持滑动isItemViewSwipeEnabled()的方法返回true,否则onMove()或者onSwiped()方法不会执行。默认情况下isLongPressDragEnabled()和isItemViewSwipeEnabled()返回true;
ItemTouchHelperCallback是个接口,包含处理拖动和滑动后的方法,代码如下:ItemTouchHelperCallback.java
public interface ItemTouchHelperCallback { /** * 移动item * @param fromPosition 起始位置 * @param toPosition 结束位置 */ void onMove(int fromPosition, int toPosition); /** * 删除item * @param position */ void onItemDelete(int position);}
第三步:对拖动和滑动后的事件进行响应处理
对RecyclerView进行拖动后,条目的位置变化了,滑动后,条目移除了,这些变化最终的展示效果,必须通知Adapter来实现,所以Adapter实现接口ItemTouchHelperCallback,具体代码如下:HotFgListStrAdapter.java
public class HotFgListStrAdapter extends RecyclerView.Adapter<HotFgListStrAdapter.TextViewHolder> implements ItemTouchHelperCallback { private List<String> mDatas; private LayoutInflater mInflater; public HotFgListStrAdapter(List<String> mDatas) { this.mDatas = mDatas; } @Override public TextViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { mInflater = LayoutInflater.from(parent.getContext()); return new TextViewHolder(mInflater.inflate(R.layout.item_hot_fg_list2, parent, false)); } @Override public void onBindViewHolder(TextViewHolder holder, final int position) { holder.mTvTitle.setText(mDatas.get(position)); holder.mTvTitle2.setText(mDatas.get(position)); } @Override public int getItemCount() { return mDatas.size(); } @Override public void onMove(int fromPosition, int toPosition) { Collections.swap(mDatas, fromPosition, toPosition); notifyItemMoved(fromPosition, toPosition); } @Override public void onItemDelete(int position) { mDatas.remove(position); notifyItemRemoved(position); } /** * 文字item的holder */ class TextViewHolder extends RecyclerView.ViewHolder{ private TextView mTvTitle, mTvTitle2; public TextViewHolder(View itemView) { super(itemView); mTvTitle = (TextView) itemView.findViewById(R.id.hot_fg_item_tv); mTvTitle2 = (TextView) itemView.findViewById(R.id.hot_fg_item_tv2); } }}
notifyItemMoved(…)、notifyItemRemoved(…)、notifyItemChanged(…)等等针对一条或者连续多条数据进行更新,这个很方便,不用因为一条数据改变,而调用notifyDataSetChanged()来通知多所有数据刷新。建议使用这个方法。代码到这里其实已经实现文章开头的效果了,但是滑动删除一条条目的体验不好,如果我们滑动后显示一个删除按钮,体验会更好一些。
第四步:功能升级,优化用户体验
现在我们在滑动过程中显示一个删除图标,删除过程中再增加一个动画。这个效果不是很麻烦,前面我们写过一个方法onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
该方法是移动过程中绘制item的回调,当actionState == ItemTouchHelper.ACTION_STATE_SWIPE时,即为滑动时候绘制背景和删除图片,具体代码如下:
/** * 移动过程中绘制item * @param c * @param recyclerView * @param viewHolder * @param dX 表示x轴移动距离 * @param dY 表示y轴移动距离 * @param actionState 当前item的状态 * @param isCurrentlyActive 如果当前用户在操作则为true,否则为false */ @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { //滑动时自己实现背景及图片 if (actionState==ItemTouchHelper.ACTION_STATE_SWIPE){ //dX大于0时向右滑动,小于0向左滑动 View itemView=viewHolder.itemView;//获取滑动的view Resources resources= recyclerView.getResources(); Bitmap bitmap= BitmapFactory.decodeResource(resources, R.drawable.address_delete);//获取删除指示的背景图片 int padding =40;//图片绘制的padding int maxDrawWidth=2*padding+bitmap.getWidth();//最大的绘制宽度 Paint paint=new Paint(); paint.setColor(resources.getColor(R.color.themeColor)); int x=Math.round(Math.abs(dX)); int drawWidth=Math.min(x,maxDrawWidth);//实际的绘制宽度,取实时滑动距离x和最大绘制距离maxDrawWidth最小值 int itemTop=itemView.getBottom()-itemView.getHeight();//绘制的top位置 //向右滑动 if(dX>0){ //根据滑动实时绘制一个背景 c.drawRect(itemView.getLeft(),itemTop,drawWidth,itemView.getBottom(),paint); //在背景上面绘制图片 if (x>padding){//滑动距离大于padding时开始绘制图片 //指定图片绘制的位置 Rect rect=new Rect();//画图的位置 rect.left=itemView.getLeft()+padding; rect.top=itemTop+(itemView.getBottom()-itemTop-bitmap.getHeight())/2;//图片居中 int maxRight=rect.left+bitmap.getWidth(); rect.right=Math.min(x,maxRight); rect.bottom=rect.top+bitmap.getHeight(); //指定图片的绘制区域 Rect rect1=null; if (x<maxRight){ rect1=new Rect();//不能再外面初始化,否则dx大于画图区域时,删除图片不显示 rect1.left=0; rect1.top = 0; rect1.bottom=bitmap.getHeight(); rect1.right=x-padding; } c.drawBitmap(bitmap,rect1,rect,paint); } //滑动透明度动画 float alpha = 1.0f - Math.abs(dX) / (float) itemView.getWidth(); itemView.setAlpha(alpha); //绘制时需调用平移动画,否则滑动看不到反馈 itemView.setTranslationX(dX); }else { //如果在getMovementFlags指定了向左滑动(ItemTouchHelper。START)时则绘制工作可参考向右的滑动绘制,也可直接使用下面语句交友系统自己处理 super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } }else { //拖动时有系统自己完成 super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } }
这一步做完后,运行效果如下:
文章到这里就结束了,文章有不对的地方,欢迎指正^_^。这里推荐github上的一个开源项目,继承ListView实现的滑动条目进行处理操作。
- RecyclerView实现滑动和拖拽功能(带小例子)
- RecyclerView实现滑动删除和拖拽功能
- RecyclerView 实现滑动删除和拖拽功能
- RecyclerView 简单实现拖拽和滑动
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- RecyclerView+CardView使用总结(带小例子)
- RecyclerView借助ItemTouchHelper实现拖动和滑动删除功能
- RecyclerView实现拖动排序和滑动删除功能
- RecyclerView拖拽排序和滑动删除实现
- RecyclerView学习--item实现拖拽和滑动删除
- 实现带header和footer功能的RecyclerView
- 带滑动菜单的Recyclerview实现
- RecyclerView 实现一个小功能
- HTML5模仿刮奖效果-页面涂抹消失插件wScratch
- PageRank算法--从原理到实现
- 仿电商应用中搜索模块的实现【GreenDao数据库存储数据】
- mysql sql语句大全【转】
- Flask Web开发--前言
- RecyclerView实现滑动和拖拽功能(带小例子)
- org.apache.commons.io.FileUtils的使用
- 递归
- Linux系统启动流程
- 每个程序猿应该阅读的10本经典书籍
- Android 软键盘控制方法、以及开发中遇到的一些问题。
- 利刃 MVVMLight 4:绑定和绑定的各种使用场景
- android5.0之后如何获取当前运行的应用包名和应用名称
- VIM基本快捷键汇总