【问题标题】:Android Navigation Component: Start at a different destination than home, programmatically?Android导航组件:以编程方式从与家不同的目的地开始?
【发布时间】:2019-06-26 08:24:14
【问题描述】:

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

到目前为止,我已经设法修改 NavigationExtensions 文件以实现所有选项卡的单个导航图,并且我得到了多个 navControllers 和它们自己的后台堆栈,但我不知道如何启动导航在不同的目的地绘制图表。

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

【问题讨论】:

    标签: android android-architecture-navigation android-jetpack-navigation


    【解决方案1】:

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

    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);
      
    4. 然后根据您的要求,您可以使用 setStartDestination 在 NavGraph 上设置起始目的地,然后将 NavGraph 应用到 NavController:

          if (condition) {
              navGraph.setStartDestination(R.id.screen1);
          } else {
              navGraph.setStartDestination(R.id.screen2);
          }
          navController.setGraph(navGraph);
      

    【讨论】:

    • 非常感谢,这让我离解决问题又近了一步。有没有办法将参数传递给作为起始目的地传递的片段?我有一个片段在传递不同的 id 时会加载不同的数据。
    • 我已经在使用安全参数,但是指令创建了一个动作,它应该被传递给带有.navigate(action) 的 NavController,它不能作为 startDestination 传递给 navGraph。有死人吗?
    • 感谢@akubi 就像魅力一样,但在此之后导航返回按钮无法按预期工作。它总是在返回按钮上关闭应用程序
    • @AhsanSaeed 我遇到了同样的问题。将app:defaultNavHost="true" 留在androidx.fragment.app.FragmentContainerView 中可以修复它。 Android参考says:“app:defaultNavHost="true"属性确保你的NavHostFragment拦截系统返回按钮。注意只有一个NavHost可以是默认的。如果你在同一个布局中有多个主机(双窗格布局,例如),请务必仅指定一个默认值 NavHost。"
    • 然而,就我而言,即使我一直使用app:startDestinationapp:defaultNavHost="true",它仍然有效。我认为我的案例的主要问题是从 xml 资源和运行时设置 navGraph。
    【解决方案2】:

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

    _main_graph
     |
     |_nested_graph_1
       |
       |_nested_graph_2  
         |
         |_nested_graph_3
           |
           |_nested_graph_4
             |
             |_change this destination!!!!  
    
    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
    }
    

    用法:

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

    【讨论】:

    • 如何处理嵌套图的退出。假设您在嵌套图 3 并且单击按钮时您必须到达嵌套图 1?
    • 这个解决方案并不具体。您可以自定义功能以满足您的需求。
    • @WISHA 你问的是其他问题。我确信我在实施它时做了一些事情,但我现在不记得了。我会尽量记住解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    相关资源
    最近更新 更多