如何在Jetpack Compose的Modal Bottom Sheet中阻止LazyColumn内的向下滑动关闭弹窗
如何在Jetpack Compose的Modal Bottom Sheet中阻止LazyColumn内的向下滑动关闭弹窗
嗨,我完全懂你这个烦恼——在Modal Bottom Sheet里的LazyColumn滑到顶后,再往下拽居然把整个弹窗关了,这体验确实糟心。别担心,咱们用Compose的嵌套滚动拦截机制就能搞定,只让顶部的拖动Handle触发弹窗关闭,LazyColumn内部的下滑操作就乖乖被列表消费掉,不会传给父布局。
下面是具体的实现步骤和代码:
- 首先,咱们需要持有LazyColumn的滚动状态,用来判断列表是否已经滑到了顶部:
val lazyListState = rememberLazyListState()
- 接着定义一个
NestedScrollConnection,它就像一个滚动事件的“守门人”,用来决定哪些滚动事件该传给父布局,哪些该自己消费:
val nestedScrollConnection = remember { object : NestedScrollConnection { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { // 判断LazyColumn是否还能向上滚动(也就是没到顶) val canScrollUp = lazyListState.firstVisibleItemIndex > 0 || lazyListState.firstVisibleItemScrollOffset > 0 // 如果列表已经到顶,且用户还在向下拖动(available.y < 0 对应手指向下滑的动作) return if (!canScrollUp && available.y < 0) { // 把这个滚动事件彻底消费掉,不让Modal Bottom Sheet接收到 available } else { // 正常传递事件,让列表自己处理滚动 Offset.Zero } } } }
- 最后把这个嵌套滚动连接绑定到LazyColumn的Modifier上,同时把LazyListState传给列表:
// 先定义Modal Bottom Sheet的状态 val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false) val scope = rememberCoroutineScope() ModalBottomSheet( onDismissRequest = { scope.launch { sheetState.hide() } }, sheetState = sheetState, dragHandle = { BottomSheetDefaults.DragHandle() } // 保持拖动Handle的功能 ) { LazyColumn( state = lazyListState, modifier = Modifier .nestedScroll(nestedScrollConnection) // 绑定滚动拦截 .fillMaxWidth() ) { // 这里放你的列表项,比如模拟100条数据 items(100) { index -> Text( text = "列表条目 $index", modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 12.dp) ) } } }
这样一来,当你在LazyColumn里滑到顶部后再向下拖动,这个动作会被列表自己消费,Modal Bottom Sheet就不会误触发关闭了;只有当你拖动顶部的官方DragHandle时,才会正常关闭弹窗,完全符合你的需求~
备注:内容来源于stack exchange,提问作者Josef M
相关产品推荐
相关产品推荐

