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

Jetpack Compose中Bottom Sheet置于Bottom Bar上方及自定义peekHeight的实现方案

我来帮你搞定这个问题!你现在遇到的Bottom Sheet显示在Bottom Bar下方的问题,本质是布局层级的顺序搞错了,同时我们还能轻松自定义它的peekHeight属性。下面是具体的解决方案:

核心解决思路
  1. 调整布局层级:把ModalBottomSheetLayout放到Scaffold的content内部,让Bottom Sheet能覆盖整个Scaffold(包括底部导航栏)
  2. 自定义peekHeight:通过ModalBottomSheetLayout的sheetPeekHeight参数直接设置初始可见高度
  3. 适配Bottom Sheet Navigator逻辑:调整导航器中的状态监听,确保和自定义peekHeight兼容
修改后的完整代码

1. 调整AppRouter的布局结构

@ExperimentalMaterialNavigationApi
@ExperimentalMaterialApi
@Composable
fun AppRouter() {
    val navController = rememberNavController()
    // 自定义peekHeight,这里设置为120.dp,你可以根据需求调整
    val customPeekHeight = 120.dp
    
    val bottomSheetNavigator = rememberFullScreenBottomSheetNavigator(
        skipHalfExpanded = true,
        customPeekHeight = customPeekHeight
    )
    navController.navigatorProvider += bottomSheetNavigator

    TriumfTaxiTheme {
        // Scaffold作为外层,Bottom Bar属于Scaffold的一部分
        Scaffold(
            bottomBar = { BuildBottomBar(navController) },
            content = { paddingValues ->
                // ModalBottomSheetLayout放在Scaffold的content里,让Bottom Sheet覆盖在所有内容之上
                ModalBottomSheetLayout(
                    bottomSheetNavigator = bottomSheetNavigator,
                    sheetPeekHeight = customPeekHeight, // 设置自定义的peek高度
                    sheetShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp) // 可选:给Bottom Sheet加圆角
                ) {
                    Box(modifier = Modifier.padding(paddingValues)) {
                        NavHost(
                            navController = navController,
                            startDestination = BottomNavScreenDestinations.BottomNavMap.route
                        ) {
                            composable(route = BottomNavScreenDestinations.BottomNavMap.route) {
                                Home()
                            }
                            // 示例Bottom Sheet路由
                            bottomSheet(route = "something") {
                                Box(
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .height(400.dp)
                                        .background(Color.White),
                                    contentAlignment = Alignment.Center
                                ) {
                                    Text(text = "我的Bottom Sheet内容")
                                }
                            }
                        }
                    }
                }
            }
        )
    }
}

2. 更新rememberFullScreenBottomSheetNavigator逻辑

@ExperimentalMaterialNavigationApi
@ExperimentalMaterialApi
@Composable
fun rememberFullScreenBottomSheetNavigator(
    animationSpec: AnimationSpec<Float> = SwipeableDefaults.AnimationSpec,
    skipHalfExpanded: Boolean = true,
    customPeekHeight: Dp = 0.dp
): BottomSheetNavigator {
    val screenHeight = LocalConfiguration.current.screenHeightDp.dp
    
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden,
        animationSpec = animationSpec,
        // 计算半展开比例,匹配自定义的peekHeight
        halfExpandedRatio = if (skipHalfExpanded) (customPeekHeight / screenHeight).value else 0.5f
    )

    if (skipHalfExpanded) {
        LaunchedEffect(sheetState) {
            snapshotFlow { sheetState.isAnimationRunning }
                .collect { isRunning ->
                    if (!isRunning) {
                        with(sheetState) {
                            // 自动跳过半展开状态,直接切换到展开或隐藏
                            if (currentValue == ModalBottomSheetValue.HalfExpanded) {
                                animateTo(ModalBottomSheetValue.Expanded)
                            }
                        }
                    }
                }
        }
    }

    return remember(sheetState) {
        BottomSheetNavigator(sheetState = sheetState)
    }
}
关键说明
  • 布局层级调整:原代码中ModalBottomSheetLayout包裹Scaffold,导致Bottom Sheet渲染在Scaffold(包括Bottom Bar)下方;调换层级后,Bottom Sheet会覆盖整个Scaffold界面。
  • peekHeight自定义:通过sheetPeekHeight参数直接设置Bottom Sheet的初始可见高度,同时在导航器中计算halfExpandedRatio,确保跳过半展开状态的逻辑和自定义高度兼容。
  • 视觉优化:可以给ModalBottomSheetLayout添加sheetShape属性,让Bottom Sheet顶部呈现圆角,提升界面美观度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:02:39