Android 导航组件:以编程方式从与家不同的目的地开始?

Luc*_* P. 15 android android-architecture-navigation android-jetpack-navigation

我正在尝试根据github 示例实现navigation controller具有多个返回堆栈的多个BottomNavigationView。但是,该示例为每个选项卡使用了不同的导航图,这使事情变得简单。在我的情况下,我需要对所有选项卡使用相同的导航图,但起始目的地与导航图中设置的“主页目的地”不同。

到目前为止,我已经设法修改NavigationExtensions文件以实现所有选项卡的单个导航图,并且我获得了多个navControllers带有自己的后堆栈的导航图,但我无法弄清楚如何在不同的目的地启动导航图。

.navigate在获取导航控制器时尝试使用,但由于它还没有连接,所以它不起作用。关于如何实现这一目标的任何想法?谢谢你。

aku*_*ubi 45

我们有一个要求,其中显示的开始屏幕取决于用户是否已登录,我们所做的如下:

  1. 删除导航上的 app:startDestination(XML如果存在)
  2. 在您的主要活动的 XML 上,删除<fragment>标签内的以下字段: app:defaultNavHost="true"app:navGraph
  3. 在我们的主 Activity 上onCreate(),我们创建一个NavGraph对象:

    NavController navController = Navigation.findNavController(this, R.id.your_nav_hostfragment);    
    NavGraph navGraph = navController.getNavInflater().inflate(R.navigation.your_navigation_xml);
    
    Run Code Online (Sandbox Code Playgroud)
  4. 然后根据您的要求,您可以使用 setStartDestination 在 NavGraph 上设置起始目的地,然后将 NavGraph 应用到 NavController:

        if (condition) {
            navGraph.setStartDestination(R.id.screen1);
        } else {
            navGraph.setStartDestination(R.id.screen2);
        }
        navController.setGraph(navGraph);
    
    Run Code Online (Sandbox Code Playgroud)

  • 谢谢@akubi,它的工作方式就像魅力,但在此之后,导航后退按钮无法按预期工作。它总是通过后退按钮关闭应用程序 (2认同)
  • 但是,就我而言,即使我一直使用 `app:startDestination` 和 `app:defaultNavHost="true"`,它仍然有效。我认为我的案例的主要问题是从 xml 资源和运行时设置 navGraph。 (2认同)

Mor*_*goo 5

我写了两个扩展来完成这项工作。首先是用于更改当前节点中的目的地。第二个是用来多次遍历成嵌套图

_main_graph
 |
 |_nested_graph_1
   |
   |_nested_graph_2  
     |
     |_nested_graph_3
       |
       |_nested_graph_4
         |
         |_change this destination!!!!  
Run Code Online (Sandbox Code Playgroud)
fun NavController.changeNodeDestination(nodeId: Int, destinationId: Int): NavController {
    val graph = graph.findNode(nodeId) as NavGraph
    graph.startDestination = destinationId
    return this
}

fun NavController.changeNodeDestination(vararg nodeIds: Int, destinationId: Int): NavController {
    var currentNode = graph

    nodeIds.forEachIndexed { index, i ->
        currentNode = currentNode.findNode(nodeIds[index]) as NavGraph
    }
    currentNode.startDestination = destinationId
    return this
}
Run Code Online (Sandbox Code Playgroud)

用法:

        findNavController().changeNodeDestination(
            R.id.navigation_login,
            R.id.nav_change_password,                  // GO two levels inside nested graphs
            destinationId = startDestination
        ).navigate(navID, bundle)
Run Code Online (Sandbox Code Playgroud)