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

Modal Bottom Sheet高度设置求助:如何自定义弹窗高度?

解决Modal Bottom Sheet高度适配问题

要实现大屏完整显示、小屏占80%屏幕且不侵入状态栏的效果,你需要结合系统窗口Insets和屏幕高度判断来设置最大高度,而非用屏幕宽度判断。以下是具体实现方案:

核心思路

  1. 获取屏幕可用显示高度:扣除状态栏、导航栏等系统UI占用的空间,避免内容侵入系统状态栏。
  2. 动态判断设备尺寸:设定一个大屏高度阈值(比如600dp),低于该阈值的小屏设备将Bottom Sheet高度限制为可用高度的80%;大屏设备则让内容自然展开,不限制最大高度。

修改后的代码实现

@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun TripListModalWithDetails(
    state: TripListViewState,
    uiIntent: (TripListUiIntent) -> Unit
) {
    val sheetState = rememberModalBottomSheetState(
        skipPartiallyExpanded = true
    )
    // 获取系统窗口Insets(状态栏、导航栏等系统UI的间距)
    val windowInsets = WindowInsets.systemBars.asPaddingValues()
    // 获取屏幕配置信息
    val configuration = LocalConfiguration.current
    // 屏幕总高度(单位:dp)
    val screenHeightDp = configuration.screenHeightDp.dp
    // 计算可用显示高度:总高度减去状态栏和导航栏的高度
    val availableHeight = screenHeightDp - windowInsets.calculateTopPadding() - windowInsets.calculateBottomPadding()
    // 自定义大屏阈值,可根据需求调整
    val largeScreenThreshold = 600.dp
    // 计算Bottom Sheet的最大允许高度
    val maxSheetHeight = if (screenHeightDp < largeScreenThreshold) {
        availableHeight * 0.8f
    } else {
        // 大屏不限制高度,让内容自然展开
        Float.POSITIVE_INFINITY.dp
    }

    if (state.detailsId != null) {
        ModalBottomSheet(
            onDismissRequest = { uiIntent(TripListUiIntent.HideTripDetails) },
            sheetState = sheetState,
            tonalElevation = TONAL_ELEVATION,
            dragHandle = {}
        ) {
            Column(
                modifier = Modifier
                    .background(MaterialTheme.colorScheme.background)
                    .padding(vertical = MaterialTheme.whereNowSpacing.space24)
                    .padding(horizontal = MaterialTheme.whereNowSpacing.space16)
                    // 应用计算好的最大高度
                    .maxHeight(maxSheetHeight)
                    .verticalScroll(rememberScrollState())
            ) {
                Text(
                    modifier = Modifier.align(Alignment.CenterHorizontally),
                    text = stringResource(R.string.trip_modal_departure),
                    style = MaterialTheme.typography.titleLarge.copy(MaterialTheme.colorScheme.primary)
                )
                HorizontalDivider(
                    modifier = Modifier.padding(
                        vertical = MaterialTheme.whereNowSpacing.space16,
                        horizontal = MaterialTheme.whereNowSpacing.space8
                    )
                )
                // 剩余内容...
            }
        }
    }
}

关键说明

  • WindowInsets的作用:通过WindowInsets.systemBars获取系统UI的间距,确保Bottom Sheet内容不会被状态栏、导航栏遮挡,也不会侵入这些系统区域。
  • 用高度判断设备尺寸:垂直方向的显示空间是你要适配的核心,用屏幕高度作为判断依据比宽度更合理。
  • 动态maxHeight:小屏时限制为可用高度的80%,保证内容有足够显示空间同时不占满屏幕;大屏时不限制高度,让内容完整展示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:42:39