是否可以在 Android/Jetpack Compose 中预填充导航后台?
我有一个深层链接,可以深入导航层次结构,但是,按后退时,它会导航到根路线。
示例:
Route.Main -> Route.List -> Route.Details(参数:id)
深层链接: https://mywebsite.com/details/id
当前行为: 它使用正确的参数打开 Route.Details,但是,在 onBack 时,它打开 Route.Main
期望的行为: 它应该打开 Route.List
我知道我可以手动“编程”此行为,但我更愿意“配置”它。
我以前也遇到过类似的问题,似乎这是图书馆的预期行为。我的意思是,如果用户从显示 Screen_C 的深层链接打开应用程序,然后按返回,则应显示应用程序的主屏幕。所以也许您需要重新验证应用程序的可用性。
但是,即使您想解决手动处理后压的问题。使用下面的功能
fun navigatingBack(
navController: NavHostController,
destinationRoute: String
) {
val hasBackstackTheDestinationRoute = navController.backQueue.find {
it.destination.route == destinationRoute
} != null
// if the destination is already in the backstack, simply go back
if (hasBackstackTheDestinationRoute) {
navController.popBackStack()
} else {
// otherwise, navigate to a new destination popping the current destination
navController.navigate(destinationRoute) {
navController.currentBackStackEntry?.destination?.route?.let {
popUpTo(it) {
inclusive = true
}
}
}
}
}
假设您声明了屏幕
ScreenA
、ScreenB
和 ScreenC
。
composable("__A__") {
ScreenA(navController)
}
composable("__B__") {
ScreenB(navController)
}
composable("__C__") {
ScreenC(navController)
}
您可以执行以下操作:
@Composable
fun ScreenA(navController: NavHostController) {
Button(onClick = {
navController.navigate("__B__")
}) {
Text(text = "Screen A - Go to B")
}
}
@Composable
fun ScreenB(navController: NavHostController) {
Button(onClick = {
navController.navigate("__C__")
}) {
Text(text = "Screen B - Go to C")
}
BackHandler {
navigatingBack(navController, "__A__")
}
}
@Composable
fun ScreenC(navController: NavHostController) {
Text(text = "Screen C")
BackHandler {
navigatingBack(navController, "__B__")
}
}
使用上面的示例,如果您直接导航到
ScreenC
并按返回,则会显示 ScreenB
。类似的情况也发生在 ScreenB
中,按下后退按钮时会显示 ScreenA
。
要使用较新版本的
navigation-compose
更新 @nglauber 的答案,您不再有权访问 navController.backQueue
,我建议像这样扩展 NavHostController
。
/**
* Attempt to pop up to the destination. If the destination is present
* in the back stack then it will pop up to it. If the destination
* is not present in the back stack it will navigate to it and remove
* the current screen from the stack.
*/
fun NavHostController.popUpTo(route: String) {
try {
this.getBackStackEntry(route)
popBackStack(route, false)
} catch (exception: IllegalArgumentException) {
navigate(route) {
currentBackStackEntry?.destination?.route?.let {
popUpTo(it) {
inclusive = true
}
}
}
}
}
然后,当你想使用它时,它会被简化为
BackHandler {
navController.popUpTo("__A__")
}