You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现RecyclerView侧滑至删除按钮宽度后停止并保持状态

问题描述

将RecyclerView条目侧滑至最大距离后松开手指,期望黑色布局保持不动、红色删除按钮持续显示,但实际松开后黑色布局会变宽覆盖删除按钮。

相关代码

row_content.xml

<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal">

<LinearLayout
    android:background="#000000"
    android:id="@+id/whiteLayout"
    android:layout_height="300dp"
    android:layout_width="0dp"
    android:orientation="horizontal"
    android:outlineProvider="none"
    android:translationZ="10dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">
</LinearLayout>


<TextView
    android:background="#FE3B30"
    android:gravity="center_vertical"
    android:id="@+id/deleteButton"
    android:layout_height="0dp"
    android:layout_width="wrap_content"
    android:paddingLeft="22dp"
    android:paddingRight="22dp"
    android:text="Delete"
    android:textColor="#FFFFFF"
    android:textSize="18dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

SwipeHelper.java

public class SwipeHelper extends ItemTouchHelper.SimpleCallback {
public SwipeHelper(int dragDirs, int swipeDirs) {
    super(dragDirs, swipeDirs);
}

@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) {

}

@Override
public float getSwipeEscapeVelocity(float defaultValue) {
    return Float.MAX_VALUE;
}

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

@Override
public void onChildDraw(
        @NonNull Canvas c,
        @NonNull RecyclerView recyclerView,
        @NonNull RecyclerView.ViewHolder viewHolder,
        float dX,
        float dY,
        int actionState,
        boolean isCurrentlyActive) {

    if (dX >= 0) {
        super.onChildDraw(
                c,
                recyclerView,
                viewHolder,
                dX,
                dY,
                actionState,
                isCurrentlyActive);
        return;
    }

    MainActivity.ContentViewHolder contentViewHolder =
            (MainActivity.ContentViewHolder) viewHolder;
    LinearLayout whiteLayout = contentViewHolder.getWhiteLayout();
    TextView deleteButton = contentViewHolder.getDeleteButton();

    ConstraintLayout.LayoutParams layoutParams =
            (ConstraintLayout.LayoutParams) whiteLayout.getLayoutParams();

    if (-dX >= deleteButton.getWidth()) {
        layoutParams.setMargins(
                layoutParams.leftMargin,
                layoutParams.topMargin,
                deleteButton.getWidth(),
                layoutParams.bottomMargin);

        whiteLayout.setLayoutParams(layoutParams);
    } else {
        layoutParams.setMargins(
                layoutParams.leftMargin,
                layoutParams.topMargin,
                (int) -dX,
                layoutParams.bottomMargin);

        whiteLayout.setLayoutParams(layoutParams);
    }

}


}

解决方案

核心问题是松开手指后,ItemTouchHelper会自动重置View的滑动状态,导致手动设置的margin被还原。按以下步骤修改:

  1. 添加状态记录变量
    在SwipeHelper类中添加成员变量,记录布局是否完全展开、删除按钮宽度:
private boolean isExpanded = false;
private int deleteBtnWidth = 0;
  1. 修改onChildDraw逻辑,固定滑动状态
    不再手动修改LayoutParams,而是通过控制dX参数固定滑动位置,让ItemTouchHelper保持最终状态:
@Override
public void onChildDraw(
        @NonNull Canvas c,
        @NonNull RecyclerView recyclerView,
        @NonNull RecyclerView.ViewHolder viewHolder,
        float dX,
        float dY,
        int actionState,
        boolean isCurrentlyActive) {

    MainActivity.ContentViewHolder contentViewHolder = (MainActivity.ContentViewHolder) viewHolder;
    LinearLayout whiteLayout = contentViewHolder.getWhiteLayout();
    TextView deleteButton = contentViewHolder.getDeleteButton();

    // 缓存删除按钮宽度,避免重复计算
    if (deleteBtnWidth == 0) {
        deleteBtnWidth = deleteButton.getWidth();
    }

    // 处理左滑逻辑
    if (dX < 0) {
        // 已展开则固定dX值,保持删除按钮完全显示
        if (isExpanded) {
            dX = -deleteBtnWidth;
        } else {
            // 限制最大滑动距离不超过删除按钮宽度,达到后标记展开状态
            if (-dX >= deleteBtnWidth) {
                dX = -deleteBtnWidth;
                isExpanded = true;
            }
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        return;
    }

    // 右滑时重置展开状态
    if (dX >= 0) {
        isExpanded = false;
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
}
  1. 优化布局(可选)
    将黑色布局的layout_width改为match_parent,滑动时视觉效果更稳定:
<LinearLayout
    android:background="#000000"
    android:id="@+id/whiteLayout"
    android:layout_height="300dp"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:outlineProvider="none"
    android:translationZ="10dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">
</LinearLayout>

内容的提问来源于stack exchange,提问作者msl12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:15:55