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

Jetpack Compose中BottomSheetScaffold嵌套LazyColumn滚动异常问题

解决Jetpack Compose中嵌套LazyColumn的BottomSheet滚动冲突问题

在Jetpack Compose中使用BottomSheet嵌套LazyColumn时,会出现滚动行为异常:滚动到列表底部后向上回滚,有时BottomSheet会提前收起,而非继续滚动到LazyColumn顶部。需要实现仅当LazyColumn处于顶部位置时,BottomSheet才响应向上滚动并收起的效果。

解决方案思路

核心是利用Compose的嵌套滚动机制,让LazyColumn优先处理滚动事件,只有当它无法再向上滚动(已处于顶部)时,才将滚动事件传递给BottomSheet。

修改后的完整代码

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun NestedScrollBottomSheet(
    content: @Composable () -> Unit,
) {
    val scaffoldState = rememberBottomSheetScaffoldState()
    val numbers = remember { (1 .. 100).toList() }
    // 获取LazyColumn的滚动状态
    val lazyListState = rememberLazyListState()
    
    // 自定义嵌套滚动连接,控制事件分发逻辑
    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                // 判断列表是否还能向上滚动(未处于顶部)
                val canScrollUp = lazyListState.canScrollBackward
                // 当用户向上滚动且列表已到顶时,不消费事件,交给BottomSheet处理
                return if (!canScrollUp && available.y < 0) {
                    Offset.Zero
                } else {
                    // 其他情况,消费事件,让LazyColumn自己处理滚动
                    available
                }
            }
        }
    }

    BottomSheetScaffold(
        scaffoldState = scaffoldState,
        sheetShape = RoundedCornerShape(0.dp),
        sheetPeekHeight = 94.dp,
        sheetDragHandle = {},
        sheetContent = {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .offset(y = 1.dp)
                    .border(
                        1.dp,
                        MainBorderBase,
                        shape = RoundedCornerShape(
                            topStart = 12.dp,
                            topEnd = 12.dp,
                            bottomEnd = 0.dp,
                            bottomStart = 0.dp
                        )
                    )
            ) {
                // 给LazyColumn绑定自定义滚动连接
                LazyColumn(
                    state = lazyListState,
                    modifier = Modifier.nestedScroll(nestedScrollConnection)
                ) {
                    items(numbers) { number ->
                        Row(
                            modifier = Modifier
                                .fillMaxWidth()
                                .height(40.dp)
                                .padding(horizontal = 16.dp),
                            verticalAlignment = Alignment.CenterVertically
                        ) {
                            Text(
                                "$number",
                                color = Color.White
                            )
                        }
                    }
                }
            }
        },
        content = {
            content()
        }
    )
}

关键逻辑说明

  • lazyListState.canScrollBackward:判断LazyColumn是否还能向上滚动(即当前第一个可见项不是列表的最顶部元素)。
  • onPreScroll:在滚动事件被消费前触发,返回Offset.Zero表示不消费该事件,事件会传递给父布局(BottomSheet);返回available表示消费事件,由LazyColumn自行处理滚动。
  • 经过上述处理,只有当LazyColumn滚到顶部无法再向上滚动时,向上的滚动操作才会触发BottomSheet收起,其他场景下滚动都由LazyColumn处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:57:22