android列表侧滑删除,Android 基于RecyclerView的Item侧滑删除

RecyclerView的强大之处就不用多说了,谁用谁知道哦,本着学习的态度我们来给RecyclerView加上侧滑删除Item的功能,话不多说,先看图:

9bfed6e127cc

ItemRemoveRecyclerView

Gif效果不够理想,呜呜......

其实核心思想很简单,就是通过重写RecyclerView的onTouchEvent()方法来检测手势的变化实现的,大致的流程如下:

1、根据手指触摸的坐标点找到对应Item的ViewHolder,进而得到相应的Item布局View。

2、手指继续移动,在条件满足的情况下,通过scrollBy()使Item布局View内容跟随手指一起移动,当然要注意边界检测。

3、手指抬起时,根据Item布局View内容移动的距离以及手指的滑动速度,判断是否显示删除按钮,进而通过startScroll()使Item布局View自动滑动到目标位置。

4、点击删除按钮则删除对应Item,点击其它区域则隐藏删除按钮。

由于Item的侧滑删除效果需要通过Scroller辅助实现的,还不了解Scroller的同学可以看下这篇文章:Android Scroller实现View弹性滑动完全解析。

接下来看一下具体的实现过程:

先看一下onTouchEvent的MotionEvent.ACTION_DOWN事件处理:

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 (mDeleteBtnState == 0) {

View view = findChildViewUnder(x, y);

if (view == null) {

return false;

}

MyViewHolder viewHolder = (MyViewHolder) getChildViewHolder(view);

mItemLayout = viewHolder.layout;

mPosition = viewHolder.getAdapterPosition();

mDelete = (TextView) mItemLayout.findViewById(R.id.item_delete);

mMaxLength = mDelete.getWidth();

mDelete.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

mListener.onDeleteClick(mPosition);

mItemLayout.scrollTo(0, 0);

mDeleteBtnState = 0;

}

});

} else if (mDeleteBtnState == 3) {

mScroller.startScroll(mItemLayout.getScrollX(), 0, -mMaxLength, 0, 200);

invalidate();

mDeleteBtnState = 0;

return false;

} else {

return false;

}

break;

case MotionEvent.ACTION_MOVE:

break;

case MotionEvent.ACTION_UP:

break;

}

mLastX = x;

mLastY = y;

return super.onTouchEvent(e);

}

我们规定删除按钮有四个状态(mDeleteBtnState):0:关闭,1:将要关闭,2:将要打开,3:打开

当删除按钮未展示时,即if (mDeleteBtnState == 0)时,通过findChildViewUnder()方法得到触摸点对应的Item View,接下来通过getChildViewHolder()得到对应的ViewHolder,有了ViewHolder,我们就可以解析出Item的布局mItemLayout以及当前Item的下标mPosition,最后得到mMaxLength ,即删除按钮的宽度也就是Item的最大滑动距离,同时给删除按钮绑定事件。

当else if (mDeleteBtnState == 3)时,Item上的删除按钮完全展示,如果点击删除按钮外的任意区域则通过startScroll()方法使Item自动右滑直到删除按钮完全隐藏,并且onTouchEvent()方法返回flase,这样此次事件结束,不会继续传递。

如果前两个条件都不满足,表示上一次Item的滑动操作尚未结束,则直接返回false,保证上一次的滑动操作顺利完成。

onTouchEvent的MotionEvent.ACTION_MOVE事件处理代码如下:

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:

break;

case MotionEvent.ACTION_MOVE:

int dx = mLastX - x;

int dy = mLastY - y;

int scrollX = mItemLayout.getScrollX();

if (Math.abs(dx) > Math.abs(dy)) {

isItemMoving = true;

if (scrollX + dx <= 0) {//左边界检测

mItemLayout.scrollTo(0, 0);

return true;

} else if (scrollX + dx >= mMaxLength) {//右边界检测

mItemLayout.scrollTo(mMaxLength, 0);

return true;

}

mItemLayout.scrollBy(dx, 0);//item跟随手指滑动

}

break;

case MotionEvent.ACTION_UP:

break;

}

mLastX = x;

mLastY = y;

return super.onTouchEvent(e);

}

当手指滑动的时候,如果水平滑动距离大于垂直滑动距离,则通过scrollBy()方法使Item可跟随手指左右滑动,当然我们进行了滑动的边界检测,并不会出现滑动越界的情况哦!

最后看一下onTouchEvent的MotionEvent.ACTION_UP事件处理:

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:

break;

case MotionEvent.ACTION_MOVE:

break;

case MotionEvent.ACTION_UP:

if (!isItemMoving && !isDragging && mListener != null) {

mListener.onItemClick(mItemLayout, mPosition);

}

isItemMoving = false;

mVelocityTracker.computeCurrentVelocity(1000);//计算手指滑动的速度

float xVelocity = mVelocityTracker.getXVelocity();//水平方向速度(向左为负)

float yVelocity = mVelocityTracker.getYVelocity();//垂直方向速度

int deltaX = 0;

int upScrollX = mItemLayout.getScrollX();

if (Math.abs(xVelocity) > 100 && Math.abs(xVelocity) > Math.abs(yVelocity)) {

if (xVelocity <= -100) {//左滑速度大于100,则删除按钮显示

deltaX = mMaxLength - upScrollX;

mDeleteBtnState = 2;

} else if (xVelocity > 100) {//右滑速度大于100,则删除按钮隐藏

deltaX = -upScrollX;

mDeleteBtnState = 1;

}

} else {

if (upScrollX >= mMaxLength / 2) {//item的左滑动距离大于删除按钮宽度的一半,则则显示删除按钮

deltaX = mMaxLength - upScrollX;

mDeleteBtnState = 2;

} else if (upScrollX < mMaxLength / 2) {//否则隐藏

deltaX = -upScrollX;

mDeleteBtnState = 1;

}

}

//item自动滑动到指定位置

mScroller.startScroll(upScrollX, 0, deltaX, 0, 200);

isStartScroll = true;

invalidate();

mVelocityTracker.clear();

break;

}

mLastX = x;

mLastY = y;

return super.onTouchEvent(e);

}

当手指抬起时,如果之前没有发生Item水平滑动、上下滑动列表、回调接口不为空,则认为是Item的点击事件,执行回调接口里的方法mListener.onItemClick(mItemLayout, mPosition);。接下来计算出手指在水平以及垂直方向的滑动速度**xVelocity 、yVelocity ,如果if (Math.abs(xVelocity) > 100 && Math.abs(xVelocity) > Math.abs(yVelocity)),则根据速度判断手指抬起后Item的滑动情况,if (xVelocity <= -100)代表左滑速度大于等于100,则将mDeleteBtnState值改为2,代表删除按钮将要打开(展示),同理如果右滑速度大于100则删除按钮将要关闭(隐藏),同时计算出相应的滑动距离deltaX **。如果不满足通过速度的判断条件则根据Item的滑动距离来判断,如果if (upScrollX >= mMaxLength / 2),即Item左滑的距离大于等于删除按钮宽度的一半,则将mDeleteBtnState值改为2,否则将mDeleteBtnState值改为1,同时不要忘了计算deltaX的值。最后通过mScroller.startScroll(upScrollX, 0, deltaX, 0, 200);使Item滑动到指定位置。

到这里我们的onTouchEvent()实现原理就分析完了。

再贴一下computeScroll()的代码:

public void computeScroll() {

if (mScroller.computeScrollOffset()) {

mItemLayout.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

invalidate();

} else if (isStartScroll) {

isStartScroll = false;

if (mDeleteBtnState == 1) {

mDeleteBtnState = 0;

}

if (mDeleteBtnState == 2) {

mDeleteBtnState = 3;

}

}

}

其中isStartScroll代表手指抬起后Item自动滑动的状态,在MotionEvent.ACTION_DOWN我们将其赋值为true,代表开始自动滑动,如果自动滑动结束则会执行else if中的逻辑,重置isStartScroll、修改mDeleteBtnState最终的状态值(打开或者关闭)。

手指上下滑动列表时,我们通过onScrollStateChanged()方法,监听列表滑动的状态:

public void onScrollStateChanged(int state) {

super.onScrollStateChanged(state);

isDragging = state == SCROLL_STATE_DRAGGING;

}

以判断是否正在上下滑动列表。

到此,我们把大致的实现方法就分析完了,如有不合理的地方欢迎指出!!!如有兴趣可下载源码看看:点我下载哦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个问题其实是一个编码问题。原本这个问句是“如何recyclerview侧滑删除item”,但是被编码转换了一下。如果要回答,应该是如下: 使用RecyclerView可以通过实现ItemTouchHelper.Callback类来实现侧滑删除item的效果。在实现ItemTouchHelper.Callback类中,可以通过onSwiped()方法实现侧滑删除item。在onSwiped()方法中,可以调用RecyclerView.Adapter的notifyItemRemoved()方法来通知RecyclerView移除该item。 ### 回答2: RecyclerViewAndroid上一个强大的列表控件。它提供了不同于ListView和GridView的Item视图回收机制以及更灵活的布局管理,同时也支持ItemTouchHelper类来实现方便的侧滑删除item的功能。 ItemTouchHelper是Android Support Library中为RecyclerView提供的一个辅助类,主要是用于支持RecyclerView中的拖拽和滑动事件。为了实现RecyclerView侧滑删除item的功能,我们需要使用ItemTouchHelper类,并实现ItemTouchHelper.Callback的各个方法(onMove、onSwiped等): 1. onMove():该方法用于处理RecyclerView中拖拽事件,通常用于实现Item的移动、排序等,我们可以在该方法中添加自己的代码,实现列表Item的移动。 2. onSwiped():该方法用于处理RecyclerView中的滑动事件,通常用于实现列表Item删除等功能,我们可以在该方法中添加自己的代码,实现Item删除的操作。 在我们实现侧滑删除Item的过程中,上述两个方法都需要实现。其中,onSwiped()方法中,我们通常会使用adapter的remove()方法将Item列表中移除。 具体实现过程如下: 1.创建一个SwipeToDeleteCallback类,并继承自ItemTouchHelper.Callback类。 public class SwipeToDeleteCallback extends ItemTouchHelper.Callback { //实现 onMove() 方法 @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { return false; } //实现 onSwiped() 方法 @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { //从数据源中移除 Item //adapter.remove(viewHolder.getAdapterPosition()) } //其他的实现方法... } 2.在onCreate()方法中创建SwipeToDeleteCallback实例,并将其绑定到RecyclerView上。 SwipeToDeleteCallback swipeHandler = new SwipeToDeleteCallback(this); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeHandler); itemTouchHelper.attachToRecyclerView(recyclerView); 3.在RecyclerView的Adapter中实现remove()方法,并在onBindViewHolder()方法中为每个Item添加GestureDetector。通过监听GestureDetector的滑动事件,判断当前Item是否向右滑动,并根据滑动的方向调用ItemTouchHelper.Callback的onSwiped()方法。 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { //数据源 List<String> mDataList = new ArrayList<>(); //添加Item操作 public void addItem(String item) { mDataList.add(item); notifyItemInserted(mDataList.size() - 1); } //移除 Item 操作 public void remove(int position) { mDataList.remove(position); notifyItemRemoved(position); } // 创建 ViewHolder @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { //创建 Item 布局 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false); return new ViewHolder(view); } // 绑定 ViewHolder @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { //设置 Item 数据 holder.itemText.setText(mDataList.get(position)); //添加 GestureDetector 监听 Item 滑动事件 GestureDetectorCompat gestureDetector = new GestureDetectorCompat(holder.itemView.getContext(), new MyGestureListener(holder)); holder.itemView.setOnTouchListener((view, motionEvent) -> { gestureDetector.onTouchEvent(motionEvent); return true; }); } //获取数据源大小 @Override public int getItemCount() { return mDataList.size(); } //创建 ViewHolder static class ViewHolder extends RecyclerView.ViewHolder { private TextView itemText; ViewHolder(View itemView) { super(itemView); itemText = itemView.findViewById(R.id.item_text); } } //GestureDetector 监听器,用于监听 Item 的滑动事件 class MyGestureListener extends GestureDetector.SimpleOnGestureListener { private final ViewHolder mHolder; MyGestureListener(MyAdapter.ViewHolder holder) { mHolder = holder; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { final float xDiff = e2.getX() - e1.getX(); if (Math.abs(xDiff) > 100) { //向右滑动时调用 onSwiped()方法 if (xDiff > 0) { remove(mHolder.getAdapterPosition()); return true; } } return false; } } } 在上述功能实现过程中,我们继承了ItemTouchHelper.Callback来自定义每个Item的拖拽和滑动事件,使用ItemTouchHelper将这个Callback实例与RecyclerView绑定在一起,然后在Adapter中添加了remove()方法,以实现Item删除功能。最後,我们使用GestureDetector监听Item滑动事件,并根据滑动的方向调用ItemTouchHelper.Callback的onSwiped()方法。 在实现RecyclerView侧滑删除item的过程中,我们还可以对ItemView进行进一步的美化,例如在ItemView左右两侧添加删除和修改按钮等。总之,RecyclerView提供了足够灵活的机制,使得我们能够自由地扩展和定制列表控件的各种功能,为用户提供优秀的使用体验。 ### 回答3: RecyclerViewAndroid官方推出的一个列表控件,它比ListView具有更为灵活和高效的特性,支持数据动态更新、多种布局管理、 ItemTouchHelper操作等,而其支持的滑动操作也极大地方便了用户操作列表数据。针对RecyclerView侧滑删除item,可以通过以下方式实现。 1. ItemTouchHelper ItemTouchHelper是RecyclerView的内置工具类,可实现滑动删除、拖曳排序等操作。通过ItemTouchHelper.onSwiped()回调将删除数据源,再通过适配器的notifyItemRemoved()通知RecyclerView删除某个条目。 2. 自定义ItemDecoration 我们可以通过RecyclerViewItemDecoration来实现侧滑删除操作,通过自定义一个类继承ItemDecoration并在其onDraw()方法中绘制删除按钮,再通过onTouchEvent()方法实现删除操作,即可实现侧滑删除item。 3. 第三方库 目前市面上也有一些优秀的RecyclerView侧滑删除第三方库,如SwipeMenuRecyclerView、SwipeRecyclerView等。这些库都提供了美观且易于使用的侧滑删除控件,大大降低了开发者的工作量。 总之,RecyclerView侧滑删除功能符合用户的使用习惯,提高了用户的操作效率,是不可或缺的一个功能,希望开发者在设计列表页面时能够注重用户体验,添加RecyclerView侧滑删除功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值