1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Android之侧滑删除RecyclerView

Android之侧滑删除RecyclerView

时间:2024-01-29 18:38:06

相关推荐

Android之侧滑删除RecyclerView

前段时间做项目,有一个需求是需要做一个侧滑删除的功能。

之前由于项目赶的比较紧,所以一起工作的小伙伴用了第三方的,自己想想,这个应该不难实现。

废话不多说,先上效果图

今天权当做下笔记,这篇文章主要参考了以下两人的文章

/bigconvience/article/details/26697645

/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) {//寻找对应坐标点下的VView 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() {@Overridepublic 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;puteCurrentVelocity(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就滑动多少。

有滑动,并且滑动结束的时候,如果状态为正在打开,或者正在关闭,那么把相对应的状态修改好。(要么打开,要么关闭)

@Overridepublic void computeScroll() {//滚动是否完成,true表示还未完成if (puteScrollOffset()){mItemView.scrollTo(mScroller.getCurrX(),mScroller.getCurrY());invalidate();//有滑动,并且在滑动结束的时候}else if (isStartScroll){isStartScroll = false;if (status == CLOSING)status = CLOSE;if (status == OPENING)status = OPEN;}}@Overrideprotected void onDetachedFromWindow() {mVelocityTracker.recycle();super.onDetachedFromWindow();}@Overridepublic void onScrollStateChanged(int state) {super.onScrollStateChanged(state);isVerMoving = state == SCROLL_STATE_DRAGGING;}

最后,附上DEMO链接:/RuijiePan/DeleteRecyclerView

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。