如何在 Compose 中设置底部工作表的半展开比例?

问题描述 投票:0回答:2

在 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 中底部工作表半展开相同的行为?

android kotlin android-jetpack-compose bottom-sheet android-jetpack-compose-material3
2个回答
0
投票

是的,这是可能的。但这是一点工作。您基本上必须提供自己的类

BottomSheetScaffold
SwipeableState
的实现,以及这两个类使用的任何相关枚举、类和可组合函数。

需要关注的要点:

  • 为半展开状态
    提供第三个值
  • 提供一个对半展开进行动画处理的函数(类似于
  • BottomSheetValue
     中的函数 
    expand()
    collapse()
    )以及检查底部工作表是否半展开的属性(类似于 
    BottomSheetState
  • 将第三个
  • val isExpanded: Boolean
    添加到
    swipeable anchor
    ,其中包含您想要实现的一半扩展值(检查行
    BottomSheetScaffold
    ,这里是您要添加自定义锚点的位置)
  • 处理
  • fullHeight - peekHeightPx to Collapsed
    .semantics
    Modifier
    块中的半展开状态
您可能需要根据您的具体要求进行一些调整。设置所有内容可能需要一段时间,但一旦完成,它就会发挥作用。


0
投票
Google 问题跟踪器上有一个

功能请求 #293496563,该请求于 2024 年被 Android 团队拒绝,并附有以下评论:

自定义锚点位置和锚点集超出了材料指南的范围。如果您的设计系统需要具有自定义定位的底部表单,我们建议您在 Foundation 的

BottomSheetScaffold

 API 之上构建您自己的底部表单,该 API 提供了这些用例。


您有两个选项来实现您的用例,每个选项都有自己的权衡。

底板支架

A

AnchoredDraggable

将为您提供

    a
  • BottomSheetScaffold
     参数,允许设置以 dp 为单位的高度,该高度将定义 
    sheetPeekHeight
     状态的高度
  • 需要解决方法来关闭
  • partiallyExpanded
     并在其后面显示 
    BottomSheet
     
  • 不支持在
  • content
     外部单击时关闭 
    BottomSheet

代码

BottomSheet

输出(扩大25%):

BottomSheetScaffold

注意

根据文档和实现,

@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

A

Expanded

将为您提供

  • ModalBottomSheet
    collapsed
    partiallyExpanded
    状态
    有良好的支持
  • 通过单击外部
  • 关闭
    expanded
  • 不支持自定义
  • ModalBottomSheet
    的高度,它始终是容器高度的50%。

代码:

partiallyExpanded

输出(扩大50%):

ModalBottomSheet

注:

设置锚定位置的代码可以在

@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
    
© www.soinside.com 2019 - 2024. All rights reserved.