'Use Dialog as navigation destination with jetpack compose
A dialog can have a rather complex ui, acting more like a floating screen rather than a typical AlertDialog. Therefore it can be desired to let the dialog have its own ViewModel
and being able to navigate to it. When using the jetpack compose navigation artifact the code indicates that only one composable is shown at any time inside the NavHost
.
Is there a way to navigate to a dialog that is overlaid onto the current ui? This would be in line with how we can navigate to fragment dialogs. Thanks.
Solution 1:[1]
Aha. This is now a feature in compose navigation version 2.4.0-alpha04
From the release notes
The NavHost of the navigation-compose artifact now supports dialog destinations in addition to composable destinations. These dialog destinations will each be shown within a Composable Dialog, floating above the current composable destination.
val navController = rememberNavController()
Scaffold { innerPadding ->
NavHost(navController, "home", Modifier.padding(innerPadding)) {
composable("home") {
// This content fills the area provided to the NavHost
HomeScreen()
}
dialog("detail_dialog") {
// This content will be automatically added to a Dialog() composable
// and appear above the HomeScreen or other composable destinations
DetailDialogContent()
}
}
}
Solution 2:[2]
It's a feature request: https://issuetracker.google.com/issues/179608120 You can star it so perhaps we'll increase it's priority
Solution 3:[3]
Example:
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Screen.Menu.route
) {
// some other screens here: composable(...) { ... }
dialog(
route = "exit_dialog",
dialogProperties = DialogProperties(
dismissOnBackPress = true,
dismissOnClickOutside = true,
)
) {
Box(modifier = Modifier.width(280.dp)) {
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(10.dp))
.background(DialogBorder)
.padding(bottom = 3.dp)
.clip(RoundedCornerShape(10.dp))
.background(DialogBackground),
) {
Column {
Column(
modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(id = R.string.text_dialog_exit_title),
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
color = Color.Black
)
Text(
text = stringResource(id = R.string.text_dialog_exit_description),
fontSize = 16.sp,
fontWeight = FontWeight.Normal,
textAlign = TextAlign.Center,
color = Color.Black
)
}
Divider(color = DialogBorder)
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
Box(
modifier = Modifier
.weight(1f)
.clickable {
// dismiss dialog
navController.popBackStack()
}
.padding(horizontal = 16.dp, vertical = 8.dp),
contentAlignment = Alignment.Center
) {
Text(
text = stringResource(id = R.string.button_cancel),
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
color = Color.Black
)
}
Box(
modifier = Modifier
.fillMaxHeight()
.width(1.dp)
.background(DialogBorder),
)
Box(
modifier = Modifier
.weight(1f)
.clickable {
// go back to home other screen
navController.popBackStack(
route = "home_screen",
inclusive = false
)
}
.padding(horizontal = 16.dp, vertical = 8.dp),
contentAlignment = Alignment.Center
) {
Text(
text = stringResource(id = R.string.button_ok),
fontSize = 16.sp,
fontWeight = FontWeight.Normal,
color = Color.Black
)
}
}
}
}
}
}
}
Result:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | nwagu |
Solution 2 | Damir Mihaljinec |
Solution 3 | Mike |