【问题标题】:Navigation graph with multiple top level destinations具有多个顶级目的地的导航图
【发布时间】:2018-11-19 10:23:03
【问题描述】:

我在空闲时间实现了一个 android 应用程序(在 Kotlin 中,但这与问题无关),我尝试使用 android jetpack 和新库。我有一个带有导航抽屉的活动。我尝试关注sample sunflower app。它在主活动中使用以下组合来启用导航抽屉背后的逻辑:

appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
setSupportActionBar(findViewById(R.id.toolbar))
setupActionBarWithNavController(navController, appBarConfiguration)

此代码的注意事项:当在导航抽屉中单击时,它会自动导航到正确的片段,然后关闭抽屉并保持它们处于选中状态等所有样板代码。这很整洁,也很有效。据我了解,抽屉式导航菜单项的 ID 必须与导航图中片段的 ID 相匹配,这样它们才能相互连接。

我遇到的问题:当我使用导航抽屉转到导航图的起始片段以外的任何片段时,它将显示一个后退按钮而不是汉堡包项。这不是我所期望的,我希望它仍然是汉堡包项目,因为导航抽屉用于在同等级别的视图之间导航而不是相互嵌套,对吧?如果我通过单击该片段中的元素(例如列表 -> 详细信息)导航到任何片段的子片段,我希望有一个后退按钮,但如果我使用导航抽屉导航则不会。

现在我将这个问题追溯到AppBarConfiguration 构建器,它读取构造函数并使用导航图The NavGraph whose start destination should be considered the only top level destination.,我可以通过覆盖AppBarConfiguration 返回不同的顶级目的地,而不仅仅是导航图。

但是我的问题是,为什么默认会有这种行为?它是一个错误吗?如果我覆盖它,我会违反谷歌的一些设计指南吗?导航抽屉中的每个元素不应该与我期望的一样吗?是否有针对我想要做的其他解决方案?

【问题讨论】:

    标签: android navigation-drawer android-navigation android-jetpack


    【解决方案1】:

    您不必重写 AppBarConfiguration。由于版本alpha7 AppBarConfiguration 有一个构造函数,其中包含所有顶级目的地的一组ID。

    Set<Integer> topLevelDestinations = new HashSet<>();
    topLevelDestinations.add(R.id.fragment1);
    topLevelDestinations.add(R.id.fragment2);
    appBarConfiguration = new AppBarConfiguration.Builder(topLevelDestinations)
                                                 .setDrawerLayout(drawerLayout)
                                                 .build();
    NavigationUI.setupActionBarWithNavController(this, 
                                                 this.navController,
                                                 this.appBarConfiguration);
    

    这不是默认的,因为导航图只有一个起始片段,它应该始终是应用程序的单一入口点。

    使用 AppBarConfiguration 编辑默认行为不会使其行为像以前一样,每个顶级片段都放置在后退堆栈中,因此后退按钮将转到所有顶级片段。目前尚不清楚如何将顶级片段作为后堆栈的第一个元素。

    【讨论】:

    • 哦,我没有注意到 AppBarConfiguration 只使用 nav_graph 来获取顶级目的地,然后将其丢弃。至少这是我假设的,因为 AppBarConfiguration 没有用于 nav_graph 的吸气剂。谢谢,我会尽可能尝试。由于这是一个空闲时间项目,我需要在有时间的时候看看。
    • 显然我们需要深入研究 JavaDoc 才能发现这个解决方案存在。我正在寻找顶级目的地规范大约 2 小时。这只是针对此问题的 SO 答案。希望有很多支持即将到来
    • 感谢您的帮助。对我来说,它不显示后退按钮仍然很奇怪,但允许您返回到 firstTopLevelDestination
    【解决方案2】:

    我为这个问题做了一个简单的例子。 https://github.com/isaul32/android-sunflower

    首先创建一组顶级目的地

    val topLevelDestinations = setOf(R.id.garden_fragment,
            R.id.plant_list_fragment)
    appBarConfiguration = AppBarConfiguration.Builder(topLevelDestinations)
            .setDrawerLayout(drawerLayout)
            .build()
    

    然后像这样覆盖 onSupportNavigateUp 函数

    override fun onSupportNavigateUp(): Boolean {
        return NavigationUI.navigateUp(navController, appBarConfiguration)
    }
    

    【讨论】:

    • 只有在使用默认的ActionBar 时才需要覆盖onSupportNavigateUp() 的最后一步。如果您添加自己的ToolBar,则此行为在调用NavigationUI.setupWithNavController(Toolbar toolbar, NavController navController, AppBarConfiguration configuration) 时已经实现。
    【解决方案3】:

    要获得具有多个顶级目的地的工具栏和抽屉的正确行为,您可以使用以下代码:

    val navController = Navigation.findNavController(this, R.id.nav_host_fragment)
    val toolbar = findViewById<Toolbar>(R.id.toolbar)
    val drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout)
    
    /*
    Create AppBarConfiguration with set of top level destinations and drawerLayout
    Set contains ids of your navigation graph screens
    */
    val appBarConfiguration = AppBarConfiguration(
        setOf(R.id.defaultFragment, R.id.firstFragment, R.id.secondFragment), 
        drawer_layout
    )
    
    //finally configure toolbar
    toolbar.setupWithNavController(navController, appBarConfiguration)
    

    此代码将确保在您的所有顶级目的地上都显示汉堡包图标,并且在您深入导航时会出现后退按钮。

    阅读更多here

    【讨论】:

    • 您能否指出您的答案与已接受答案的不同之处?对我来说,它们似乎是等价的。
    【解决方案4】:

    你可以像这样直接使用目的地的ID

    mAppBarConfiguration = new AppBarConfiguration.Builder(R.id.salahTimeFragment,
                R.id.nav_home,R.id.navslideFragment, R.id.nav_feedback,R.id.nav_tap_count,R.id.nav_templete,R.id.nav_add_topic)
                .setDrawerLayout(drawer)
                .build();
    

    但我不知道它仅在菜单 id(activity_main_drawer) 和目标 id(mobile_navigation.xml) 相同时才有效。 如果有人解释原因,那将是很大的帮助

    【讨论】:

      【解决方案5】:

      setOf 和 setDrawerLayout 被贬低,你应该使用

      AppBarConfiguration 配置 = new AppBarConfiguration.Builder(R.id.defaultFragment, R.id.firstFragment,R.id.secondFragment).setOpenableLayout(drawerLayout).build();

      【讨论】:

        猜你喜欢
        • 2020-11-09
        • 1970-01-01
        • 1970-01-01
        • 2018-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-04
        • 1970-01-01
        相关资源
        最近更新 更多