ModalBottomSheet在LazyColumn滚动停止时的滚动拦截问题
解决ModalBottomSheet与LazyColumn的滚动冲突问题
你遇到的滚动控制权跳转问题,确实可以通过自定义NestedScrollConnection来解决,核心思路是控制滚动事件的分发逻辑:只有当LazyColumn滚动到顶部时,才让ModalBottomSheet响应拖动;其他情况滚动事件完全交给LazyColumn处理。
之前用rememberNestedScrollInteropConnection()没用是因为它是为Compose和原生View系统的嵌套滚动互操作设计的,不适合Compose内部组件的滚动协调。
修改后的完整代码
@OptIn(ExperimentalMaterial3Api::class) @Composable fun SheetTest() { val sheetState = rememberModalBottomSheetState( skipPartiallyExpanded = true, confirmValueChange = { it != SheetValue.Hidden } ) val lazyListState = rememberLazyListState() // 自定义嵌套滚动连接,控制滚动事件流向 val nestedScrollConnection = remember { object : NestedScrollConnection { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { // 向上滚动时:如果LazyColumn还能往上滚,就消费掉事件,不让Sheet响应 return if (available.y < 0 && lazyListState.canScrollUp()) { available } else { Offset.Zero // 否则让Sheet处理滚动 } } } } ModalBottomSheet( sheetState = sheetState, onDismissRequest = {}, containerColor = Color.Blue ) { LazyColumn( modifier = Modifier .fillMaxSize() .nestedScroll(nestedScrollConnection), // 应用自定义滚动连接 state = lazyListState ) { items(dummyPlaces) { text -> Text( text = text, fontSize = 48.sp, color = Color.Green ) } } } }
关键逻辑说明
lazyListState.canScrollUp():判断LazyColumn是否已经滚动到顶部——返回false时表示已经到顶,此时才允许Sheet响应拖动。onPreScroll方法:在滚动事件传递给子组件(LazyColumn)前拦截,根据条件决定是否消费事件:- 向上滚动且LazyColumn还能滚动时,消费事件(返回
available),阻止Sheet获取滚动控制权; - 其他情况(比如向下滚动,或LazyColumn已到顶),不消费事件,让Sheet或LazyColumn正常响应。
- 向上滚动且LazyColumn还能滚动时,消费事件(返回
这样设置后,就能实现你想要的效果:只有拖动底部弹窗手柄,或者LazyColumn滚动到顶部时,才能拖动ModalBottomSheet;日常滚动LazyColumn时,Sheet不会再突然接管滚动控制权。
内容的提问来源于stack exchange,提问作者6rchid
相关产品推荐
相关产品推荐

