Skip to content

Instantly share code, notes, and snippets.

@stdpmk
Created April 4, 2022 13:19
Show Gist options
  • Select an option

  • Save stdpmk/3051bae2347cc5ee19ae20299a19c90f to your computer and use it in GitHub Desktop.

Select an option

Save stdpmk/3051bae2347cc5ee19ae20299a19c90f to your computer and use it in GitHub Desktop.
compose_conditional_nav
// Как лучше в Compose реализовать условную навигацию?
// Есть какие-то патерны?
// В данном примере условная навигация в методе
// navigateToB
// В зависимости от экрана на котором мы сейчас находимся, делаем тот или иной переход
// Граф
@Composable
fun MainNavGraph2(
modifier: Modifier = Modifier,
) {
val navController: NavHostController = rememberNavController()
NavHost(
navController = navController,
startDestination = "A",
modifier = modifier
) {
composable("A") {
// Главный экран с 3-мя кнопками для теста навигации
ScreenA(navController = navController)
}
composable("B") {
// B - текущий, C - куда переходим
Screen(screen = "B", toScreen = "C",
navigateToScreen = {
navigateToC(navController)
},
color = Color.Red,
)
}
composable("C") {
Screen(screen = "C", toScreen = "B",
navigateToScreen = {
navigateToB(navController)
},
color = Color.Blue
)
}
composable("D") {
// Тут показываем диалог, а уже из него (код ниже) переходим в B
Screen(screen = "D", toScreen = "dialog",
navigateToScreen = {
navigateToDialogD(navController)
},
color = Color.Yellow
)
}
dialog("dialogD") {
DialogD(
onOk = {
navigateToB(navController)
},
onDismissed = {
navController.popBackStack()
}
)
}
}
}
// Начальный экран
@Composable
fun ScreenA(
navController: NavController,
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Column {
Button(onClick = {
navigateToB(navController)
}) {
Text(text = "A->B")
}
Spacer(Modifier.padding(top = 5.dp))
Button(onClick = {
navigateToBC(navController)
}) {
Text(text = "A->(B->C). Open subchain B->C")
}
Spacer(Modifier.padding(top = 5.dp))
Button(onClick = {
navigateToD(navController)
}) {
Text(text = "A->D")
}
}
}
}
// Навигация вынесена в отдельные top level функции
// Top level function
private fun navigateToB(navController: NavController) {
val currentRoute = navController.currentBackStackEntry?.destination?.route
when(currentRoute) {
"A" -> {
navController.navigate("B")
}
"C" -> {
navController.navigate("B") {
popUpTo(0)
}
}
"D" -> {
navController.navigate("dialogD")
}
"dialogD" -> {
navController.navigate("B") {
popUpTo(0)
}
}
}
}
private fun navigateToBC(navController: NavController) {
val currentRoute = navController.currentBackStackEntry?.destination?.route
if (currentRoute == "A") {
navController.navigate("B")
navController.navigate("C")
}
}
private fun navigateToD(navController: NavController) {
navController.navigate("D")
}
private fun navigateToC(navController: NavController) {
navController.navigate("C")
}
private fun navigateToDialogD(navController: NavController) {
navController.navigate("dialogD")
}
@Composable
fun Screen(
screen: String,
toScreen: String,
color: Color = Color.Black,
navigateToScreen: () -> Unit = {}
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(color),
contentAlignment = Alignment.Center,
) {
Column {
Text(text = screen)
Button(onClick = { navigateToScreen() }) {
Text(text = "Go to $toScreen")
}
}
}
}
@Composable
fun DialogD(
onDismissed: () -> Unit = {},
onOk: () -> Unit = {},
) {
AlertDialog(
buttons = {
Button(onClick = {
onOk()
}) {
Text(text = "Ok")
}
},
title = {
Text(text = "DialogD")
},
text = {
Text(text = "Go to B")
},
onDismissRequest = {
onDismissed()
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment