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

[BUG] ModalBottomSheet with nested NavHost breaks the Composition #311

Open
tomczyn opened this issue Apr 17, 2024 · 2 comments
Open

[BUG] ModalBottomSheet with nested NavHost breaks the Composition #311

tomczyn opened this issue Apr 17, 2024 · 2 comments

Comments

@tomczyn
Copy link

tomczyn commented Apr 17, 2024

Describe the bug
When nesting a NavHost inside a ModalBottomSheet content, it shows visual glitches instead of a correct Composables. By glitches I mean nested NavHost (bottom sheet content) is being displayed on the sheet and underneath the sheet, Compose is copying the content to two places and not displaying the original NavHost at all.

What it should show, blue is a main view (whole screen home NavHost), red is bottom sheet content (150.dp height).
Zrzut ekranu 2024-04-17 o 18 45 30

What is shown, bottom sheet content displayed on the sheet and underneath it.
Zrzut ekranu 2024-04-17 o 18 48 35

Minimal reproducible example

@Composable
fun App() {
    PreComposeApp {
        MaterialTheme {
            Column(modifier = Modifier.fillMaxSize()) {
                var showBottomSheet by remember { mutableStateOf(false) }
                val navigator = rememberNavigator()
                NavHost(
                    navigator = navigator,
                    navTransition = NavTransition(),
                    initialRoute = "/home",
                ) {
                    scene(route = "/home") {
                        Column(
                            Modifier.fillMaxSize().background(Color.Blue),
                            horizontalAlignment = Alignment.CenterHorizontally
                        ) {
                            Text("Main Title")
                            Button(onClick = { showBottomSheet = true }) {
                                Text("Show bottom sheet")
                            }
                        }
                    }
                }
                if (showBottomSheet) {
                    val sheetState = rememberModalBottomSheetState()
                    val scope = rememberCoroutineScope()
                    ModalBottomSheet(
                        sheetState = sheetState,
                        onDismissRequest = { showBottomSheet = false },
                        dragHandle = null,
                        content = {
                            val sheetNavigator = rememberNavigator()
                            NavHost(  // Sheet NavHost, when removed everything starts to work correctly
                                navigator = sheetNavigator,
                                navTransition = NavTransition(),
                                initialRoute = "/sheet",
                            ) {
                                scene(route = "/sheet") {
                                    Column(
                                        Modifier.fillMaxWidth().height(150.dp)
                                            .background(Color.Red),
                                        horizontalAlignment = Alignment.CenterHorizontally
                                    ) {
                                        Text("BottomSheet Title")
                                        Button(
                                            onClick = {
                                                scope.launch { sheetState.hide() }
                                                    .invokeOnCompletion {
                                                        if (!sheetState.isVisible)
                                                            showBottomSheet = false
                                                    }
                                            }
                                        ) {
                                            Text("Hide bottom sheet")
                                        }
                                    }
                                }
                            }
                        }
                    )
                }
            }
        }
    }
}

Repo: https://github.com/tomczyn/PreCompose-Sample
Branch with StateHolder fix: https://github.com/tomczyn/PreCompose-Sample/tree/fix

Workaround

It appears that wrapping the NavHost in StateHolder solves the problem with displaying the content, but the behavior of the bottom sheet is still a little bit bugged with this workaround. Instead, it sometimes doesn't show the showing/hidding animation of the bottom sheet correctly.

val stateHolder = remember { StateHolder() }
CompositionLocalProvider(LocalStateHolder provides stateHolder) {
    NavHost( // Sheet NavHost
    ...
}
@Tlaster
Copy link
Owner

Tlaster commented Apr 18, 2024

It appears that rememberNavigator consistently returns the same Navigator. One possible workaround is to assign a unique name each time rememberNavigator is used.
Perhaps we should consider automatically assigning different names when using rememberNavigator

@tomczyn
Copy link
Author

tomczyn commented Apr 18, 2024

Thank you, that works! The most important thing is it can be very easily solved, but good point on the behavior change.

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

No branches or pull requests

2 participants