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

BottomSheet内RecyclerView滚动致Toolbar隐藏问题求解

解决BottomSheet内RecyclerView滚动导致Toolbar隐藏的问题

这个问题我之前也碰到过,本质是CoordinatorLayout的全局滚动事件传递机制在搞鬼——哪怕是BottomSheet内部的RecyclerView滚动,事件也会被AppBarLayout关联的ScrollingViewBehavior捕捉到,从而触发Toolbar的隐藏动画。给你两个靠谱的解决思路:

方案一:给BottomSheet内的RecyclerView添加自定义Behavior拦截滚动事件

我们可以写一个自定义的Behavior,拦截BottomSheet里RecyclerView的垂直滚动事件,不让它向上传递给CoordinatorLayout的其他子View(比如AppBarLayout)。

1. 实现自定义Behavior

import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.recyclerview.widget.RecyclerView
import androidx.core.view.ViewCompat

class BottomSheetRecyclerViewBehavior(context: Context, attrs: AttributeSet) : RecyclerView.Behavior(context, attrs) {

    override fun onStartNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: RecyclerView,
        directTargetChild: View,
        target: View,
        axes: Int,
        type: Int
    ): Boolean {
        // 只拦截垂直滚动事件,返回true表示我们要接管这个滚动事件的处理
        return axes == ViewCompat.SCROLL_AXIS_VERTICAL
    }

    override fun onNestedPreScroll(
        coordinatorLayout: CoordinatorLayout,
        child: RecyclerView,
        target: View,
        dx: Int,
        dy: Int,
        consumed: IntArray,
        type: Int
    ) {
        // 消耗掉垂直方向的滚动事件,不让它继续向上传递
        consumed[1] = dy
    }
}

2. 在布局中给BottomSheet的RecyclerView设置这个Behavior

找到你布局里的navRecyclerView,添加app:layout_behavior属性,指定我们刚才写的自定义Behavior(注意替换成你的包名):

<androidx.recyclerview.widget.RecyclerView 
    android:id="@+id/navRecyclerView" 
    android:layout_width="match_parent" 
    android:layout_height="0dp" 
    android:layout_marginTop="32dp" 
    android:overScrollMode="never" 
    app:elevation="0dp" 
    app:layout_constraintBottom_toBottomOf="parent" 
    app:layout_constraintEnd_toEndOf="parent" 
    app:layout_constraintHeight_default="wrap" 
    app:layout_constraintStart_toStartOf="parent" 
    app:layout_constraintTop_toBottomOf="@+id/bottomSheetTitleTextView"
    app:layout_behavior="com.your.package.name.BottomSheetRecyclerViewBehavior" />

方案二:修改BottomSheet的Behavior(简化版)

如果你不想写自定义Behavior,也可以通过重写BottomSheetBehavior的onStartNestedScroll方法,阻止滚动事件向外传递。不过这种方式需要自定义BottomSheetBehavior,灵活性稍差,但也能解决问题:

class CustomBottomSheetBehavior(context: Context, attrs: AttributeSet) : BottomSheetBehavior<View>(context, attrs) {
    override fun onStartNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: View,
        directTargetChild: View,
        target: View,
        axes: Int,
        type: Int
    ): Boolean {
        // 只让BottomSheet自己处理内部的滚动事件,不让父布局感知
        return axes == ViewCompat.SCROLL_AXIS_VERTICAL && super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type)
    }

    override fun onNestedPreScroll(
        coordinatorLayout: CoordinatorLayout,
        child: View,
        target: View,
        dx: Int,
        dy: Int,
        consumed: IntArray,
        type: Int
    ) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
        // 消耗滚动事件,避免传递给AppBarLayout
        if (type == ViewCompat.TYPE_TOUCH) {
            consumed[1] = dy
        }
    }
}

然后把布局里BottomSheet的app:layout_behavior换成这个自定义的:

<androidx.constraintlayout.widget.ConstraintLayout 
    android:id="@+id/bottomSheet" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:background="@android:color/transparent" 
    app:behavior_hideable="false" 
    app:behavior_peekHeight="88dp" 
    app:layout_behavior="com.your.package.name.CustomBottomSheetBehavior">
    <!-- 内部内容不变 -->
</androidx.constraintlayout.widget.ConstraintLayout>

两种方案里,方案一更推荐,因为它只针对BottomSheet内的RecyclerView,不会影响BottomSheet本身的拖拽行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 10:19:05