Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BottomSheet: Consider adding keys to rememberBottomSheetState #51

Open
leononame opened this issue Dec 17, 2024 · 3 comments
Open

BottomSheet: Consider adding keys to rememberBottomSheetState #51

leononame opened this issue Dec 17, 2024 · 3 comments
Labels
feature request New feature or request

Comments

@leononame
Copy link

My use case is relatively simple: I would like to get a bottom sheet that jumps to a specific height based on the content on the screen. However, that content can be dynamic, so I would like the seet size to be dynamic as well.

Take this example:

@Composable
fun TestScreen(accountId: AccountId) {
    // make a big box
    Box(Modifier.fillMaxSize().safeContentPadding().background(Color.Gray)) {
        // measured size of the content
        var contentSize by remember { mutableStateOf(IntSize.Zero) }
        // measured height is derived from the size
        val contentHeight = with(LocalDensity.current) { contentSize.height.toDp() }

        // draw a box that grows by 100.dp every time it's clicked
        var height by remember { mutableStateOf(100.dp) }
        Box(
            Modifier
                .height(height)
                .fillMaxWidth()
                .background(Color.Red)
                .clickable { height += 100.dp }
                // measure size of the box
                .onSizeChanged { contentSize = it }) {}

        // create detents
        // peek should be 50.dp below the box above
        val peek = SheetDetent(identifier = "peek") { containerHeight, _ ->
            // contentHeight is captured here, but because rememberBottomSheetState remembers it from the first time
            // the scrim was created, it's not updated
            println("calling peek with content height: $contentHeight")
            containerHeight - contentHeight - 50.dp
        }
        // fullscreen should go above the box to 90% of the content size
        val fullScreen = SheetDetent(identifier = "fullscreen") { containerHeight, _ ->
            containerHeight * 0.9f
        }
        // make sheet
        val sheetState = rememberBottomSheetState(
            detents = listOf(peek, fullScreen),
            initialDetent = peek,
        )
        BottomSheet(
            state = sheetState,
            modifier = Modifier.fillMaxWidth().background(Color.White),
        ) {
            Column(
                modifier = Modifier.fillMaxWidth(),
                horizontalAlignment = Alignment.CenterHorizontally,
            ) {
                DragIndication(
                    Modifier
                        .padding(top = 22.dp)
                        .background(Color.Black.copy(0.4f), RoundedCornerShape(100))
                        .width(32.dp)
                        .height(4.dp)
                )
                LazyColumn {
                    repeat(50) {
                        item { Text("Item #${(it + 1)}", modifier = Modifier.padding(10.dp)) }
                    }
                }
            }
        }

    }
}

The problem is that when I specify detents, their lambdas capture values during the first run and won't re-trigger afterwards. It would be nice if it was possible to force the sheetState to recalculate on specific keys, in this case e.g. contentHeight.

I would have implemented my own rememberBottomSheetState, but since the SheetState constructor is internal, I can't.

@alexstyl alexstyl added the feature request New feature or request label Dec 18, 2024
@alexstyl
Copy link
Member

Thanks for the request. Sounds very reasonable.

I'm currently busy with some other project and once that is sorted, I will be able to work on unstyled again. Can't promise on dates.

@jtomli
Copy link

jtomli commented Jan 29, 2025

+1 to this - also looking for a way to make the sheet wrap dynamic content height instead of hard coding a detent value

@LumentusLogiball
Copy link

@alexstyl I have a different use case for having keys to trigger recreation of the BottomSheetState:

For my current project I would like to be able to update the list of available detents.

For example in my current project in most cases we want to have 3 different detents, but sometimes we want to skip the middle detent.
This cannot currently be implemented with confirmDetentChange properly both because it captures the "valid" detents during the initial composition (though it is possible to workaround this by abusing Compose a bit) and because it becomes incredibly difficult for the user to "fling" across the disallowed detent, since the sheet will often think, the user wants to go to the disallowed state and blocks the change. When it blocks the movement it looks like the video shows, which does not feel like an acceptable user experience:

SheetProblem.webm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants