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
相关产品推荐
相关产品推荐

