在 XML 中,我们有 Material3 底表。它允许我们设置底部工作表的行为。它可以更新为:
bottomSheetBehavior.halfExpandedRatio = 0.6
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
我正在将项目迁移到 Compose。我的应用程序将这个半展开比例用于 3 个定位的底部工作表:折叠、半展开、展开。现在我正在尝试创建这样的底页:
val sheetState = rememberBottomSheetState(
initialValue = BottomSheetValue.Collapsed
)
val scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = sheetState
)
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetContent = {}
) {}
但看起来我们这里没有这些行为属性。我们能否获得与 XML 中底部工作表半展开相同的行为?
是的,这是可能的。但这是一点工作。您基本上必须提供自己的类
BottomSheetScaffold
和 SwipeableState
的实现,以及这两个类使用的任何相关枚举、类和可组合函数。
需要关注的要点:
提供第三个值
BottomSheetValue
中的函数
expand()
和
collapse()
)以及检查底部工作表是否半展开的属性(类似于
BottomSheetState
)
val isExpanded: Boolean
添加到
swipeable anchor
,其中包含您想要实现的一半扩展值(检查行
BottomSheetScaffold
,这里是您要添加自定义锚点的位置)
fullHeight - peekHeightPx to Collapsed
中.semantics
的Modifier
块中的半展开状态
功能请求 #293496563,该请求于 2024 年被 Android 团队拒绝,并附有以下评论:
自定义锚点位置和锚点集超出了材料指南的范围。如果您的设计系统需要具有自定义定位的底部表单,我们建议您在 Foundation 的
BottomSheetScaffold
API 之上构建您自己的底部表单,该 API 提供了这些用例。
底板支架
BottomSheetScaffold
参数,允许设置以 dp 为单位的高度,该高度将定义
sheetPeekHeight
状态的高度
partiallyExpanded
并在其后面显示
BottomSheet
content
外部单击时关闭 BottomSheet
代码
BottomSheet
输出(扩大25%):
注意
根据文档和实现,@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomSheetScaffoldDemo() {
val scope = rememberCoroutineScope()
val scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberStandardBottomSheetState(
initialValue = SheetValue.Hidden,
skipHiddenState = false
)
)
val configuration = LocalConfiguration.current
val screenHeight = configuration.screenHeightDp.dp
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetPeekHeight = screenHeight / 4, // expand to 25% of screen height
sheetContent = {
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceAround) {
Button(
onClick = {
scope.launch { scaffoldState.bottomSheetState.hide() }
}
) {
Text("HIDE")
}
Button(
onClick = {
scope.launch { scaffoldState.bottomSheetState.partialExpand() }
}
) {
Text("PARTIAL")
}
Button(
onClick = {
scope.launch { scaffoldState.bottomSheetState.expand() }
}
) {
Text("FULL")
}
}
repeat(25) {
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
text = "Line $it"
)
}
}
) { innerPadding ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(
start = innerPadding.calculateStartPadding(LocalLayoutDirection.current),
end = innerPadding.calculateEndPadding(LocalLayoutDirection.current),
top = innerPadding.calculateTopPadding(),
// do not apply bottom padding!
),
contentAlignment = Alignment.Center
) {
Button(
onClick = { scope.launch { scaffoldState.bottomSheetState.partialExpand() } }
) {
Text(text = "PARTIAL")
}
}
}
}
的
BottomSheet
应该部分展开或完全展开,而不是折叠。 Android 开发者在Issue #276929560 中的以下评论也指出了这一事实:
这是因为他们随时可能会完全取消对折叠的支持。
BottomSheetScaffold
(StandardBottomSheet
) 与 UI 共存,并且仅应处于BottomSheetScaffold
和完全PartiallyExpanded
状态。
ModalBottomSheet
ModalBottomSheet
、
collapsed
和
partiallyExpanded
状态有良好的支持
expanded
ModalBottomSheet
的高度,它始终是容器高度的50%。
代码:
partiallyExpanded
输出(扩大50%):
注:
设置锚定位置的代码可以在@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ModalBottomSheetDemo() {
var openBottomSheet by rememberSaveable { mutableStateOf(false) }
val scope = rememberCoroutineScope()
val bottomSheetState =
rememberModalBottomSheetState(skipPartiallyExpanded = false)
Box(
contentAlignment = Alignment.Center
) {
Row {
Button(
onClick = { openBottomSheet = !openBottomSheet }
) {
Text(text = "PARTIAL")
}
}
}
if (openBottomSheet) {
ModalBottomSheet(
onDismissRequest = { openBottomSheet = false },
sheetState = bottomSheetState,
) {
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceAround) {
Button(
onClick = {
scope
.launch { bottomSheetState.hide() }
.invokeOnCompletion {
if (!bottomSheetState.isVisible) {
openBottomSheet = false
}
}
}
) {
Text("HIDE")
}
Button(
onClick = {
scope.launch { bottomSheetState.partialExpand() }
}
) {
Text("PARTIAL")
}
Button(
onClick = {
scope.launch { bottomSheetState.expand() }
}
) {
Text("FULL")
}
}
repeat(25) {
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
text = "Line $it"
)
}
}
}
}
文件中找到,您将在
ModalBottomSheet.kt
可组合项中找到以下代码:
ModalBottomSheetContent