RecyclerView滚动时阻止其父布局折叠的技术问题求助
我之前也碰到过一模一样的坑,设置android:nestedScrollingEnabled="false"没用是因为BottomSheetBehavior的事件拦截逻辑不在嵌套滚动的流程里——它是直接在CoordinatorLayout的触摸事件分发阶段做判断的。结合你用了自定义CustomSheetBehavior的情况,给你两个靠谱的解决方案:
方案一:修改自定义BottomSheetBehavior,过滤RecyclerView的触摸事件
直接在你的CustomSheetBehavior里增加判断,当触摸的是RecyclerView时,不让BottomSheet响应拖动逻辑:
class CustomSheetBehavior<V : View>(context: Context, attrs: AttributeSet) : BottomSheetBehavior<V>(context, attrs) { override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean { // 找到BottomSheet内的RecyclerView实例 val recyclerView = child.findViewById<RecyclerView>(R.id.recyclerView) if (recyclerView != null) { val touchArea = Rect() recyclerView.getGlobalVisibleRect(touchArea) // 判断触摸点是否落在RecyclerView范围内 if (touchArea.contains(event.rawX.toInt(), event.rawY.toInt())) { // 不拦截事件,交给RecyclerView自己处理滚动 return false } } // 其他场景保持原有Behavior逻辑 return super.onInterceptTouchEvent(parent, child, event) } }
这样设置后,只有触摸BottomSheet的非RecyclerView区域(比如顶部的搜索栏)时,才会触发BottomSheet的拖动折叠;滚动RecyclerView时,BottomSheet会保持展开状态。
方案二:给RecyclerView设置触摸监听,阻止父布局拦截事件
如果不想修改自定义Behavior,也可以在代码层给RecyclerView添加触摸监听,主动阻止CoordinatorLayout拦截触摸事件:
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView) recyclerView.setOnTouchListener { view, motionEvent -> // 告诉父布局不要拦截当前触摸事件 view.parent.requestDisallowInterceptTouchEvent(true) // 手指抬起时恢复父布局的拦截权限,避免影响其他交互 if (motionEvent.action == MotionEvent.ACTION_UP) { view.parent.requestDisallowInterceptTouchEvent(false) } // 返回false,让RecyclerView自己处理滚动逻辑 false }
这个方法的核心是通过requestDisallowInterceptTouchEvent方法,切断BottomSheet对RecyclerView触摸事件的拦截路径,从而避免触发折叠。
补充:为什么android:nestedScrollingEnabled="false"不生效?
这个属性是控制RecyclerView是否参与嵌套滚动流程(比如和AppBarLayout联动的滚动),但BottomSheet的折叠是CoordinatorLayout直接通过触摸事件拦截实现的,不属于嵌套滚动的范畴,所以设置这个属性对BottomSheet的折叠逻辑完全没有影响。
内容的提问来源于stack exchange,提问作者rengineer

