如何为BottomSheet设置与PartiallyExpanded等高的最小高度?
Material3 ModalBottomSheet 半展开状态高度计算逻辑及应用
需求说明
我自定义了一个BottomSheet组件(代码如下),通过rememberModalBottomSheetState管理其状态,现在需要明确**PartiallyExpanded(半展开)**状态的高度计算逻辑,从而给这个自定义BottomSheet设置与该高度一致的最小高度。
自定义BottomSheet实现代码
@Composable @OptIn(ExperimentalMaterial3Api::class) fun BottomSheet( modifier: Modifier = Modifier, isBottomSheetVisible: Boolean, sheetState: SheetState, shape: Shape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp), onDismiss: () -> Unit, content: @Composable ColumnScope.() -> Unit ) { if (isBottomSheetVisible) { ModalBottomSheet( modifier = modifier, onDismissRequest = onDismiss, sheetState = sheetState, tonalElevation = 0.dp, shape = shape, dragHandle = null, windowInsets = WindowInsets(0, 0, 0, 0) ) { Column( modifier = Modifier .fillMaxWidth() .padding(start = 16.dp, end = 16.dp, bottom = 30.dp) .navigationBarsPadding() .animateContentSize() ) { Spacer(modifier = Modifier.height(10.dp)) Box( modifier = Modifier .size(height = 4.dp, width = 32.dp) .clip(RoundedCornerShape(100.dp)) .background(almaColorPalette.neutral4) .align(alignment = Alignment.CenterHorizontally) ) Spacer(modifier = Modifier.height(15.dp)) content() } } } }
状态初始化代码
val sheetState = rememberModalBottomSheetState()
半展开状态高度的源码计算逻辑
Material3中ModalBottomSheet的半展开高度计算逻辑封装在核心源码里,核心规则如下:
- 基础比例:默认取屏幕可用高度的50%,这里的可用高度是指屏幕总高度减去系统窗口Insets(状态栏、导航栏等系统占据的高度)。
- 源码核心逻辑:
在calculatePartiallyExpandedHeight方法中,核心计算逻辑简化后如下:
注:大屏设备(如平板)会根据窗口尺寸类调整比例,但手机端默认是50%可用高度。private fun calculatePartiallyExpandedHeight( windowSizeClass: WindowSizeClass, windowInsets: WindowInsets ): Dp { val usableHeight = windowSizeClass.windowHeightDp - windowInsets.getTop(LocalDensity.current) - windowInsets.getBottom(LocalDensity.current) return usableHeight * 0.5f } - 额外约束:计算出的半展开高度不会小于底部导航栏高度,同时如果内容自身高度小于该计算值,会以内容实际高度为准。
给自定义BottomSheet设置对应最小高度
要让自定义BottomSheet的最小高度匹配系统半展开高度,可按以下步骤实现:
获取窗口相关参数
在Composable中获取窗口尺寸类和系统Insets:val windowSizeClass = calculateWindowSizeClass(LocalContext.current) val windowInsets = WindowInsets.systemBars val density = LocalDensity.current计算半展开高度
按照源码逻辑计算目标高度:val partiallyExpandedHeight = with(density) { val usableHeight = windowSizeClass.windowHeightDp.dp - windowInsets.getTop(this) - windowInsets.getBottom(this) usableHeight * 0.5f }应用最小高度到组件
修改自定义BottomSheet中的Column修饰符,添加minimumHeight约束:Column( modifier = Modifier .fillMaxWidth() .padding(start = 16.dp, end = 16.dp, bottom = 30.dp) .navigationBarsPadding() .animateContentSize() .minimumHeight(partiallyExpandedHeight) // 添加最小高度约束 ) { // 原有内容保持不变 }
这样就能确保自定义BottomSheet的最小高度与系统默认的半展开高度完全一致。
内容的提问来源于stack exchange,提问作者onesector
相关产品推荐
相关产品推荐

