19

I basically have the same problem as this post, except I'm using Jetpack Compose, instead of the old View model. It happens with any kind of content - I tested it with a simple Text composable. Here's how to reproduce it:

  1. Set the Text composable to display a string that ends up making it 6 lines high
  2. Change the text (while the Bottom Sheet stays expanded) to only be 1 line high. In my test case, I just made it so that clicking the text would change it
  3. The top of the Text composable stays at the previous level, and the bottom "jumps" up for a split second to make up the height difference. Then the whole composable drops back down, and ends up at the bottom of the screen, where it was supposed to have been all along

This only happens when the new content is shorter in height then the original (that's why I tested it with 6 lines worth of text changing to 1 line). The original post I referenced says that the solution is to setandroid:animateLayoutChanges = "false", however, I don't see any equivalent in Compose. There's a modifier for animateContentSize, but it's only to enable animation. I don't see any option to disable it.

Here's my sample code:

ModalBottomSheetLayout(
        sheetContent = {
            var text by remember{ mutableStateOf("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum")}
            Text(text = text, Modifier.clickable {
                text = "a much shorter line of text"
            })
        },
        sheetShape = RoundedCornerShape(12.dp),
    ) { ... }
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
user496854
  • 6,461
  • 10
  • 47
  • 84

3 Answers3

1

It's a bug in ModalBottomSheetLayout → https://issuetracker.google.com/258744762

0

I think you can use SubcomposeLayout to measure the text's max height. Then, wrap the Text with a Box using the max height calculated in the subcomposition.

You can use the composable function below as sheetContent parameter.

@Composable
fun BottomSheetContent() {
    var maxHeight = remember { 0.dp }
    var text by remember { mutableStateOf("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum") }

    val localDensity = LocalDensity.current
    SubcomposeLayout { constraints ->
        // Measuring the Text size...
        val contentPlaceable = subcompose("SomeRandomIdForThisContent") {
            Text(text = text,
                Modifier
                    .clickable {
                        text = "a much shorter line of text"
                    }
            )
        }.first()
            .measure(constraints)
        val height = contentPlaceable.height
        val heightInDp = with(localDensity) { ((height + 1) / density).dp }
        // Updating the max height
        if (maxHeight == 0.dp || heightInDp > maxHeight) {
            maxHeight = heightInDp
        }

        layout(contentPlaceable.width, maxHeight.roundToPx()) {
            contentPlaceable.placeRelative(0, 0)
        }
    }
}

Here's the result:

enter image description here

nglauber
  • 18,674
  • 6
  • 70
  • 75
  • That's a novel approach, but I do want the sheet size to change when content changes -- I just need it to look "normal", meaning that the top of the sheet will drop to the proper level (instead of the bottom jumping up, and then dropping back down) – user496854 Apr 05 '22 at 14:00
  • 1
    @user496854 Did you find any solution for that? thanks – Udi Oshi May 29 '22 at 08:37
  • No, I ended up just making a custom version of the Bottom Sheet, where I can fully control the layout – user496854 May 29 '22 at 15:32
  • Is it possible for you to share what you achieved? I still have troubles with my custom version of bottom sheet. @user496854 – Mohammad May 25 '23 at 05:56
0

One not so great way to do this is to use fixed size and a scrollable view. Like you can set the height of the expanded bottom sheet to .height(0.4f) and so the bottom sheet won't be shrinking anymore on content height changes.

Raul Lucaciu
  • 132
  • 7