Android之侧滑删除RecyclerView
2016-10-27 14:35
316 查看
前段时间做项目,有一个需求是需要做一个侧滑删除的功能。
之前由于项目赶的比较紧,所以一起工作的小伙伴用了第三方的,自己想想,这个应该不难实现。
废话不多说,先上效果图
今天权当做下笔记,这篇文章主要参考了以下两人的文章
http://blog.csdn.net/bigconvience/article/details/26697645
http://www.jianshu.com/p/9bfed6e127cc
网上实现该功能的一大堆,大多使用的是ItemTouchHelper这个辅助类,大家有兴趣可以搜一下相关资料看看,不过今天我这边用另一种方法实现。
如图所示,我们可以看到。一个侧滑删除的动作,我们可以分为4部分,我们用0,1,2,3来代表,分别代表删除图片的状态:关闭、将要关闭
、将要打开、打开。
那么,首先我们要自定义一个recyclerview,让它继承原有的recyclerview。代码如下:
接着,我们主要对onTouch事件进行重写。
当(state ==CLOSE)时,Item上的删除按钮完全展示,如果点击删除按钮外的任意区域则通过startScroll()方法使Item自动右滑直到删除按钮完全隐藏,并且onTouchEvent()方法返回flase,这样此次事件结束,不会继续传递。
如果前两个条件都不满足,表示上一次Item的滑动操作尚未结束,则直接返回false,保证上一次的滑动操作顺利完成。
接下来就是MotionEvent.ACTION_HOVER_MOVE的事件处理:
滑动的时候,我们要处理的主要就是判断是否越界:当中有两个临界点
1.位于初始位置,手指向右滑动,图片不能移动
2.删除图片已经完全打开,手指向左滑动,图片不能移动
只要处理好这两个点,其他状态下,手指滑动多少,对应的view就滑动多少
最后就是对MotionEvent.ACTION_UP:的事件处理:
这里可以分为两种情况进行处理:
1.滑动的时候滑动速度很快,假如是向左滑动打开删除图片,那么即使滑动距离不大,那么也应该完整的打开删除图片
2.滑动的时候滑动速度比较慢,那么如果抬起手指的时候,删除图片打开不到它宽度的1/2,那么就应该关闭删除图片的显示。如果超过1/2,那么就应该完整地显示删除图片
最后就是重写一下computeScroll()方法和回收VelocityTracker
滑动未完成的时候,手指滑动多少,对应的view就滑动多少。
有滑动,并且滑动结束的时候,如果状态为正在打开,或者正在关闭,那么把相对应的状态修改好。(要么打开,要么关闭)
最后,附上DEMO链接:https://github.com/RuijiePan/DeleteRecyclerView
之前由于项目赶的比较紧,所以一起工作的小伙伴用了第三方的,自己想想,这个应该不难实现。
废话不多说,先上效果图
今天权当做下笔记,这篇文章主要参考了以下两人的文章
http://blog.csdn.net/bigconvience/article/details/26697645
http://www.jianshu.com/p/9bfed6e127cc
网上实现该功能的一大堆,大多使用的是ItemTouchHelper这个辅助类,大家有兴趣可以搜一下相关资料看看,不过今天我这边用另一种方法实现。
如图所示,我们可以看到。一个侧滑删除的动作,我们可以分为4部分,我们用0,1,2,3来代表,分别代表删除图片的状态:关闭、将要关闭
、将要打开、打开。
那么,首先我们要自定义一个recyclerview,让它继承原有的recyclerview。代码如下:
public class DeleteRecyclerView extends RecyclerView { private Context mContext; private VelocityTracker mVelocityTracker; private Scroller mScroller; public DeleteRecyclerView(Context context) { this(context,null); } public DeleteRecyclerView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public DeleteRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; mScroller = new Scroller(context,new LinearInterpolator()); //构建滑动速度检测的类 mVelocityTracker = VelocityTracker.obtain(); }
接着,我们主要对onTouch事件进行重写。
public boolean onTouchEvent(MotionEvent e) { mVelocityTracker.addMovement(e); //获取当前坐标 int x = (int) e.getX(); int y = (int) e.getY(); switch (e.getAction()){ case MotionEvent.ACTION_DOWN: //删除图片还没打开的状态 if (status == CLOSE) { //寻找对应坐标点下的V View view = findChildViewUnder(x, y); if (view == null) { return false; } //通过baseviewholder获取对应的子View,详情可以看代码 BaseViewHolder viewHolder = (BaseViewHolder) getChildViewHolder(view); mItemView = viewHolder.getView(R.id.item_layout); mPosition = viewHolder.getAdapterPosition(); mDeleteView = viewHolder.getView(R.id.item_delete); mMaxLength = mDeleteView.getWidth(); mDeleteView.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { //返回原点 mItemView.scrollTo(0,0); status = CLOSE; if (mListener!=null) mListener.onDeleteClick(mPosition); } }); //当删除图片已经完全显示的时候 }else if (status == OPEN){ //从当前view的偏移点mItemView.getScrollX(),位移-mMaxLength长度单位 // 时间DEFAULT_TIMEms,向左移动为正数 mScroller.startScroll(mItemView.getScrollX(),0,-mMaxLength,0,DEFAULT_TIME); //刷新下一帧动画 invalidate(); status = CLOSE; return false; }else { return false; } break;
当(state ==CLOSE)时,Item上的删除按钮完全展示,如果点击删除按钮外的任意区域则通过startScroll()方法使Item自动右滑直到删除按钮完全隐藏,并且onTouchEvent()方法返回flase,这样此次事件结束,不会继续传递。
如果前两个条件都不满足,表示上一次Item的滑动操作尚未结束,则直接返回false,保证上一次的滑动操作顺利完成。
接下来就是MotionEvent.ACTION_HOVER_MOVE的事件处理:
滑动的时候,我们要处理的主要就是判断是否越界:当中有两个临界点
1.位于初始位置,手指向右滑动,图片不能移动
2.删除图片已经完全打开,手指向左滑动,图片不能移动
只要处理好这两个点,其他状态下,手指滑动多少,对应的view就滑动多少
case MotionEvent.ACTION_MOVE: //获取上次的落点与当前的坐标之间的差值 int dx = mLastX - x; int dy = mLastY - y; int scrollX = mItemView.getScrollX(); //水平滑动距离大于垂直距离 if (Math.abs(dx)>Math.abs(dy)){ isHorMoving = true; //向左滑动,直至显示删除图片,向左滑动的最大距离不超过删除图片的宽度 if (scrollX+dx>=mMaxLength){ mItemView.scrollTo(mMaxLength,0); return true; //向右滑动,直至删除图片不显示,向右滑动的最大距离不超过初始位置 }else if (scrollX+dx<=0){ mItemView.scrollTo(0,0); return true; } //如果在图片还未完全显示的状态下,那么手指滑动多少,图片就移动多少 mItemView.scrollBy(dx,0); //mItemView.scrollTo(dx+scrollX,0); } break;
最后就是对MotionEvent.ACTION_UP:的事件处理:
这里可以分为两种情况进行处理:
1.滑动的时候滑动速度很快,假如是向左滑动打开删除图片,那么即使滑动距离不大,那么也应该完整的打开删除图片
2.滑动的时候滑动速度比较慢,那么如果抬起手指的时候,删除图片打开不到它宽度的1/2,那么就应该关闭删除图片的显示。如果超过1/2,那么就应该完整地显示删除图片
case MotionEvent.ACTION_UP: if (!isHorMoving && !isVerMoving && mListener!=null){ mListener.onItemClick(mItemView,mPosition); } isHorMoving = false; mVelocityTracker.computeCurrentVelocity(1000);//计算手指滑动的速度 float xVelocity = mVelocityTracker.getXVelocity();//水平方向速度(向左为负) float yVelocity = mVelocityTracker.getYVelocity();//垂直方向速度 int upScrollX = mItemView.getScrollX(); int deltaX = 0 ; //向右滑动速度为正数 //滑动速度快的状态下抬起手指,计算所需偏移量 if (Math.abs(xVelocity)>Math.abs(yVelocity) && Math.abs(xVelocity)>=VELOCITY ){ //向右隐藏 if (xVelocity >= VELOCITY){ deltaX = -upScrollX; status = CLOSING; }else if (xVelocity <= -VELOCITY){ deltaX = mMaxLength - upScrollX; status = OPENING; } //滑动速度慢的状态下抬起手指,如果滑动距离大于1/2的图片宽度,计算偏移量 //不够的话恢复原点 }else { if (upScrollX >= mMaxLength/2){ deltaX = mMaxLength - upScrollX; status = OPENING; }else { deltaX = -upScrollX; status = CLOSING; } } mScroller.startScroll(upScrollX,0,deltaX,0,DEFAULT_TIME); isStartScroll = true; invalidate(); mVelocityTracker.clear(); break; } mLastX = x; mLastY = y; return super.onTouchEvent(e); }
最后就是重写一下computeScroll()方法和回收VelocityTracker
滑动未完成的时候,手指滑动多少,对应的view就滑动多少。
有滑动,并且滑动结束的时候,如果状态为正在打开,或者正在关闭,那么把相对应的状态修改好。(要么打开,要么关闭)
@Override public void computeScroll() { //滚动是否完成,true表示还未完成 if (mScroller.computeScrollOffset()){ mItemView.scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); invalidate(); //有滑动,并且在滑动结束的时候 }else if (isStartScroll){ isStartScroll = false; if (status == CLOSING) status = CLOSE; if (status == OPENING) status = OPEN; } } @Override protected void onDetachedFromWindow() { mVelocityTracker.recycle(); super.onDetachedFromWindow(); } @Override public void onScrollStateChanged(int state) { super.onScrollStateChanged(state); isVerMoving = state == SCROLL_STATE_DRAGGING; }
最后,附上DEMO链接:https://github.com/RuijiePan/DeleteRecyclerView
相关文章推荐
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- Android实现RecyclerView侧滑删除和长按拖拽
- Android基础控件——RecyclerView实现拖拽排序侧滑删除效果
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- android的RecyclerView实现拖拽排序和侧滑删除示例
- Android 仿QQ界面的 RecyclerView 侧滑删除效果
- Android——实现RecyclerView左侧滑删除与右侧滑选择
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- Android 仿QQ侧滑删除—一个满足ListView、RecyclerView以及其他View通用的侧滑删除
- android RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载
- Android基础——RecyclerView拖拽排序侧滑删除
- 【Android开源项目解析】RecyclerView侧滑删除粒子效果实现——初探Android开源粒子库 Leonids
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- 【Android开源项目解析】RecyclerView侧滑删除粒子效果实现——初探Android开源粒子库 Leonids
- Android侧滑删除的Recyclerview
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- Android开发——使用高级的RecyclerView实现侧滑菜单删除功能(SwipeRecyclerView)
- Android开发之RecyclerView的侧滑删除
- Android-详解RecyclerView+BGARefreshLayout实现自定义下拉刷新、上拉加载和侧滑删除效果
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能