RecyclerView - 使用ItemTouchHelper实现侧滑删除效果


前言

我们平时在QQ过程中,有一个效果是我们不可忽略的,那就是消息记录的侧滑删除功能。

一、概述

如上的效果是怎么实现之前,我们来看看上面效果都有那几个问题需要考虑的:

  1. 怎么实现左右侧滑?ItemTouchHelper?ItemTouchHelper怎么实现侧滑之后不删除,而是停留在某种状态上。
  2. 从上面的效果图中,我们可以明确的感受到左右滑动都可以超出RecyclerView的边界,只是在手指松开之后,ItemView会回到正确的位置而已。像这种overscroll效果应该怎么实现?
  3. 当停留在删除状态时,此时ItemView还可以从左右滑动(QQ只能向右滑动)。这种效果又应该怎么实现呢?

针对上面的三个问题,本文会详细的分析是怎么实现的。

二、了解ItemTouchHelper.Callback

  我们知道,ItemTouchHelper的核心在于ItemTouchHelper.Callback接口中,所以在正式分析实现之前,我们先来了解temTouchHelper.Callback的几个方法。

方法名 作用
getSwipeThreshold 当 侧滑滑动的距离 / RecyclerView的宽大于该方法返回值,那么就会触发侧滑删除的操作。具体是:此时ItemView会做位移动画,当ItemView不可见时,会触发ItemTouchHelper的onSwiped方法,进而我们在onSwiped方法里面对Adapter进行remove操作。
getSwipeEscapeVelocity 当侧滑的速度大于该方法的返回值,也会触发侧滑删除的操作。
onChildDraw 此为核心方法,该方法在ItemView进行滑动时会回调,这里的滑动包括:1.手指滑动;2.ItemView的位移动画。可以根据isCurrentlyActive参数来判断是手指滑动还是动画滑动。
clearView 为核心方法,该方法在ItemView滑动完成之后会回调,所以想要实现侧滑ItemView停在某种状态,此方法是核心之点。

  经过对上面几个方法的理解,现在,我来简单描述一下效果的实现方法:
  首先我们将滑动距离的阈值和滑动速度的阈值设置到最大,保证不会触发原本的侧滑删除操作。
  当手指滑动时,我们就让它开心的滑动,不去怎么做任何的操作;当手指松开时,因为速度阈值和距离阈值都是最大,所以不可能超过它,那么ItemView会做动画回到最初的状态,但是我们不能按照原来的规则来位移ItemView,所以我们得判断手指松开那时ItemView的滑动距离是否大于我们设置的阈值(是否显示删除按钮的阈值),如果大于的话,那么就做动画到给定的位置就行,如果小于的话,就回到原始位置。

三、如何实现

  现在我们正式来看一下代码,首先看一下getSwipeThreshold方法getSwipeEscapeVelocity方法:
代码如下(示例):

    @Override
    public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
   
        return Integer.MAX_VALUE;
    }

    @Override
    public float getSwipeEscapeVelocity(float de
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RecyclerView侧滑菜单可以通过ItemTouchHelper类来实现。 首先,需要创建一个实现ItemTouchHelper.Callback的类,重写其中的方法,用于处理拖拽和侧滑等操作。在其中,我们需要实现onSwiped方法,用于处理RecyclerView中的侧滑操作。 可以通过实现onChildDraw方法来绘制侧滑菜单,例如使用Canvas绘制背景和图标等。然后在onSwiped方法中,通过ViewHolder.getAdapterPosition()获取当前侧滑的位置,然后再调用Adapter的remove方法来删除对应的数据。最后,需要在Adapter中实现onCreateViewHolder方法,在其中绑定侧滑菜单的布局和操作。 下面是一个简单的示例代码: ```java public class SwipeController extends ItemTouchHelper.Callback { private RecyclerView.Adapter adapter; public SwipeController(RecyclerView.Adapter adapter) { this.adapter = adapter; } @Override public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { return makeMovementFlags(0, ItemTouchHelper.LEFT); } @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { return false; } @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { int position = viewHolder.getAdapterPosition(); adapter.notifyItemRemoved(position); adapter.notifyItemRangeChanged(position, adapter.getItemCount()); } @Override public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { View itemView = viewHolder.itemView; Paint p = new Paint(); if (dX < 0) { p.setColor(Color.RED); RectF background = new RectF((float)itemView.getRight() + dX, (float)itemView.getTop(), (float)itemView.getRight(), (float)itemView.getBottom()); c.drawRect(background, p); Drawable icon = ContextCompat.getDrawable(adapter.getContext(), R.drawable.ic_delete); int iconWidth = icon.getIntrinsicWidth(); int iconHeight = icon.getIntrinsicHeight(); int left = itemView.getRight() - iconWidth - 32; int top = itemView.getTop() + (itemView.getHeight() - iconHeight) / 2; int right = itemView.getRight() - 32; int bottom = top + iconHeight; icon.setBounds(left, top, right, bottom); icon.draw(c); } super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } } ``` 在Activity或Fragment中,可以将SwipeController作为参数传递给ItemTouchHelper,然后调用ItemTouchHelper.attachToRecyclerView方法来绑定RecyclerView。 ```java RecyclerView recyclerView = findViewById(R.id.recycler_view); Adapter adapter = new Adapter(data); recyclerView.setAdapter(adapter); SwipeController swipeController = new SwipeController(adapter); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController); itemTouchHelper.attachToRecyclerView(recyclerView); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值