我正在Jetpack编写导航演示,我有一个嵌套导航图,其中包含两个不同的嵌套路线和每个嵌套路线的屏幕:
- 登录图
- 主图
登录图有三条路线,用于显示三个不同的屏幕
- 显示登录屏幕的路径“登录”
- 用于显示RegisterScreen的路由“register”
- 用于显示RecoverPasswordScreen的路由“recoverPassword”
主图为这些屏幕提供了两条路径
- 路由“home”以显示主屏幕
- 用于显示SettingsScreen的路由“设置”
嵌套图的创建在 * MainActivity.kt * 中调用
setContent {
NavigationDemoTheme {
val navController = rememberNavController()
SetupNavGraph(navController = navController)
}
}
文件 NestedNavGraph.kt 中的函数如下所示:
fun SetupNavGraph(navController: NavHostController) {
NavHost(navController = navController, startDestination = "login_route")
{
loginGraph(navController = navController)
mainGraph(navController = navController)
}
}
在文件 * LoginNavGraph.kt * 中,我定义了路由和起始目的地
fun NavGraphBuilder.loginGraph(navController: NavController) {
navigation(startDestination = "login", route = "login_route") {
composable(route = "login") {
LoginScreen(navController = navController)
}
composable(route = "register") {
RegisterScreen(navController = navController)
}
composable(route = "recover") {
RecoverPasswordScreen(navController = navController)
}
}
}
在文件 MainNavGraph.kt 中,我定义了这两个路由和这个起始目的地:
navigation(startDestination = "home", route = "main_route") {
composable(route = "home") {
HomeScreen(navController = navController)
}
composable(route = "settings") {
SettingsScreen(navController = navController)
}
}
我现在的问题是如何从设置屏幕显示RecoverPasswordScreen?我知道我可以使用从设置屏幕导航到“login_route”,但随后将显示startDestination,即登录屏幕。
// shows the LoginScreen because the startDestination in the "login_route" is set to "login"
navController.navigate(route = "login_route")
那么,如何才能直接导航到嵌套图路由“login_route”中的路由“recover”呢?以下“变通方法”在我的脑海中:
向“login_route”传递一个参数,例如:
navController.navigate(route = "login_route?destination=recover")
然后我将只有一个路由作为目的地,例如“LoginView”。这将像这样更改loginGraph:
fun NavGraphBuilder.loginGraph(navController: NavController) {
navigation(startDestination = "login_view, route = "login_route/{destination}) {
composable(
route = "login_view",
arguments = listOf(
navArgument("destination") { defaultValue = "login" },
)
) { backStackEntry ->
val destination = backStackEntry.arguments?.getString("destination");
destination?.let { destination ->
LoginView(destination = destination)
}
}
}
}
LoginView是可组合的,它将有一个自己的NavHost,我可以使用上一个路由中的查询参数设置startDestination:
fun LoginView( destination : String = "login"){
val navController = rememberNavController()
var startDestination = destination;
Scaffold ()
{
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(route = "login") {
LoginScreen(navController = navController)
}
composable(route = "register") {
RegisterScreen(navController = navController)
}
composable(route = "recover") {
RecoverPasswordScreen(navController = navController)
}
}
}
现在,我应该能够从SettingsScreen调用RecoverPasswordScreen:
navController.navigate(route = "login_route?destination=recover")
另一种可能性是在MainGraph中为RecoverPassword屏幕定义额外的路由。是否有其他可能性直接访问嵌套图中的路由?如果可以在路由到“login_route”时动态更改startDestination就太好了,但我不知道如何或是否可能。
3条答案
按热度按时间jslywgbw1#
Compose允许你(使用参数导航)。这允许你导航到你所说的“嵌套路由”,即屏幕中的特定部分。
现在,这是一个简单的解释,我可以离开你,让你弄清楚它。但我不认为这会对你有帮助,因为我认为你已经实现了你的导航在一个困难的方式。因此,为什么试图导航是有点复杂。
这里有一个更好的方法来实现它,以便像你想要的导航(从设置屏幕恢复密码屏幕)更容易。
声明
将任何称为 Main 的内容更改为您的AppName。
我还没有添加您的所有屏幕
主屏类
主活动类
设置界面
这是实现导航的最简单的方法(在我看来),因为你可以简单地添加回调来导航到应用程序中的不同位置,而且它更可测试(如果你测试;您还可以添加深层链接并使用参数(如上所述)导航到应用程序的特定部分(例如,帐户屏幕中的特定帐户)
如果你想了解更多,我强烈推荐这款Navigation Codelab。
q9yhzks02#
一个可能的解决方案是使用导航图中定义的深度链接-它们也适用于嵌套目的地。
li9yvcax3#
如果一个屏幕级的组合在我的应用程序中的不同地方被重用,我倾向于给予它一个自己的导航图,即使它是那个图中唯一的屏幕?
例如,在您的特定场景中,您将有“loginGraph”、“mainGraph”和“recoverPassword”图,其中“recoverPassword”图中的唯一目标是
RecoverPasswordScreen
。这将使您能够从应用程序中的任何位置导航到
RecoverPasswordScreen
,同时仍然为大多数流保留单独的导航图。这也可以很好地工作,因为你可能有更多的屏幕添加到恢复密码流后-例如
PasswordRecoverySuccessfulScreen()
-可以只是添加到这个新的图形。