android Jetpack Compose中的多个底页用于一个模态底页布局

pkbketx9  于 2023-06-27  发布在  Android
关注(0)|答案(4)|浏览(268)

我想实现一个屏幕,可以显示两个不同的底部工作表。由于ModalBottomSheetLayout只有一个用于一个工作表的插槽,因此我决定在想要显示两个工作表(full code)中的任何一个时,使用selected状态动态更改ModalBottomSheetLayoutsheetContent

  1. val sheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
  2. val (selected, setSelected) = remember(calculation = { mutableStateOf(0) })
  3. ModalBottomSheetLayout(sheetState = sheetState, sheetContent = {
  4. when (selected) {
  5. 0 -> Layout1()
  6. 1 -> Layout2()
  7. }
  8. }) {
  9. Content(sheetState = sheetState, setSelected = setSelected)
  10. }

这对于非常相似的工作表很有效,但是一旦您向两个工作表布局中的任何一个添加了更多的复杂性,则工作表在第一次按下按钮时将不会显示,只有在按下按钮两次后才会显示,如您所见:

Here you can find a reproducible example

cu6pst1q

cu6pst1q1#

我有一个类似的用例,我需要显示2-3个堆叠的底页。我最终复制了大部分的Compose BottomSheet,并添加了所需的行为:

  1. enum class BottomSheetValue { SHOWING, HIDDEN }
  2. @Composable
  3. fun BottomSheet(
  4. parentHeight: Int,
  5. topOffset: Dp = 0.dp,
  6. fillMaxHeight: Boolean = false,
  7. sheetState: SwipeableState<BottomSheetValue>,
  8. shape: Shape = bottomSheetShape,
  9. backgroundColor: Color = MaterialTheme.colors.background,
  10. contentColor: Color = contentColorFor(backgroundColor),
  11. elevation: Dp = 0.dp,
  12. content: @Composable () -> Unit
  13. ) {
  14. val topOffsetPx = with(LocalDensity.current) { topOffset.roundToPx() }
  15. var bottomSheetHeight by remember { mutableStateOf(parentHeight.toFloat())}
  16. val scrollConnection = sheetState.PreUpPostDownNestedScrollConnection
  17. BottomSheetLayout(
  18. maxHeight = parentHeight - topOffsetPx,
  19. fillMaxHeight = fillMaxHeight
  20. ) {
  21. val swipeable = Modifier.swipeable(
  22. state = sheetState,
  23. anchors = mapOf(
  24. parentHeight.toFloat() to BottomSheetValue.HIDDEN,
  25. parentHeight - bottomSheetHeight to BottomSheetValue.SHOWING
  26. ),
  27. orientation = Orientation.Vertical,
  28. resistance = null
  29. )
  30. Surface(
  31. shape = shape,
  32. color = backgroundColor,
  33. contentColor = contentColor,
  34. elevation = elevation,
  35. modifier = Modifier
  36. .nestedScroll(scrollConnection)
  37. .offset { IntOffset(0, sheetState.offset.value.roundToInt()) }
  38. .then(swipeable)
  39. .onGloballyPositioned {
  40. bottomSheetHeight = it.size.height.toFloat()
  41. },
  42. ) {
  43. content()
  44. }
  45. }
  46. }
  47. @Composable
  48. private fun BottomSheetLayout(
  49. maxHeight: Int,
  50. fillMaxHeight: Boolean,
  51. content: @Composable () -> Unit
  52. ) {
  53. Layout(content = content) { measurables, constraints ->
  54. val sheetConstraints =
  55. if (fillMaxHeight) {
  56. constraints.copy(minHeight = maxHeight, maxHeight = maxHeight)
  57. } else {
  58. constraints.copy(maxHeight = maxHeight)
  59. }
  60. val placeable = measurables.first().measure(sheetConstraints)
  61. layout(placeable.width, placeable.height) {
  62. placeable.placeRelative(0, 0)
  63. }
  64. }
  65. }

顶部偏移,例如允许将bottomSheet放置在AppBar下面:

  1. BoxWithConstraints {
  2. BottomSheet(
  3. parentHeight = constraints.maxHeight,
  4. topOffset = with(LocalDensity.current) {56.toDp()}
  5. fillMaxHeight = true,
  6. sheetState = yourSheetState,
  7. ) {
  8. content()
  9. }
  10. }
展开查看全部
pxy2qtax

pxy2qtax2#

我是这样实现的。它看起来很简单,但我仍然不知道如何将参数直接传递给“mutableStateOf()”,我必须创建一个变量“content”

  1. fun Screen() {
  2. val bottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
  3. val scope = rememberCoroutineScope()
  4. val content: @Composable (() -> Unit) = { Text("NULL") }
  5. var customSheetContent by remember { mutableStateOf(content) }
  6. ModalBottomSheetLayout(
  7. sheetState = bottomSheetState,
  8. sheetContent = {
  9. customSheetContent()
  10. }
  11. ) {
  12. Column {
  13. Button(
  14. onClick = {
  15. customSheetContent = { SomeComposable1() }
  16. scope.launch { bottomSheetState.show() }
  17. }) {
  18. Text("First Button")
  19. }
  20. Button(
  21. onClick = {
  22. customSheetContent = { SomeComposable2() }
  23. scope.launch { bottomSheetState.show() }
  24. }) {
  25. Text("Second Button")
  26. }
  27. }
  28. }
展开查看全部
idfiyjo8

idfiyjo83#

我想实现同样的事情,因为大的解决方案,我写了一篇文章在dev.to解决这个问题,这里是link

vd8tlhqk

vd8tlhqk4#

这个解决方案适用于 N 数量的底部片材,甚至如果你想堆叠它们也可以工作,下面是实现:

  1. typealias BottomSheetControl = Pair<ModalBottomSheetState, @Composable ColumnScope.() -> Unit>
  2. @Composable
  3. fun HeaderContentMultipleBottomSheetsTemplate(
  4. finalContent: @Composable () -> Unit,
  5. sheetsShape: Shape = ServyUIShapesDefaults.RoundedRectangle,
  6. vararg sheets: BottomSheetControl
  7. ) {
  8. HeaderContentBottomSheetsTemplateImpl(
  9. finalContent = finalContent,
  10. sheetsShape = sheetsShape,
  11. sheets = sheets,
  12. )
  13. }
  14. @Composable
  15. private fun HeaderContentBottomSheetsTemplateImpl(
  16. modifier: Modifier = Modifier,
  17. finalContent: @Composable () -> Unit,
  18. scrimColor: Color = ModalBottomSheetDefaults.scrimColor,
  19. sheetsShape: Shape = ServyUIShapesDefaults.RoundedRectangle,
  20. vararg sheets: BottomSheetControl
  21. ) {
  22. if (sheets.isNotEmpty()) {
  23. ModalBottomSheetLayout(
  24. modifier = modifier,
  25. sheetState = sheets[0].first,
  26. sheetContent = sheets[0].second,
  27. sheetShape = sheetsShape,
  28. scrimColor = scrimColor
  29. ) {
  30. HeaderContentBottomSheetsTemplateImpl(
  31. finalContent = finalContent,
  32. sheets = sheets.sliceArray(1 until sheets.size)
  33. )
  34. }
  35. } else {
  36. finalContent() // Here is your Screen Content
  37. }
  38. }

对于实现,您需要具有以下内容:

  1. // The sheet state, you can manipulate it whatever you want.
  2. val testSheetState= rememberModalBottomSheetState(
  3. initialValue = ModalBottomSheetValue.Hidden,
  4. animationSpec = tween(durationMillis = 100),
  5. confirmValueChange = { it != ModalBottomSheetValue.HalfExpanded },
  6. skipHalfExpanded = true,
  7. )
  8. // The sheet content.
  9. @Composable
  10. fun TestSheet(): @Composable ColumnScope.() -> Unit = {
  11. Text(text = "LOLLL")
  12. }
  13. // The Pair of state and content
  14. val test: BottomSheetControl = Pair(testSheetState, TestSheet())

最后,你可以:

  1. HeaderContentMultipleBottomSheetsTemplate(
  2. finalContent = {
  3. // Here the content of your screen (in ColumnScope)
  4. },
  5. sheets = arrayOf(test)
  6. )

Pd:vararg参数“sheets”中的项目顺序定义了每个项目的级别,如果你想堆叠它们,请按嵌套顺序编写。

展开查看全部

相关问题