具有多个顶级目的地的导航图

时间:2018-11-19 10:23:04

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

我在业余时间实现了一个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返回与只是导航图的起始目的地。

但是我的问题是,为什么会有这种默认行为?是虫子吗?如果我不这样做,是否会违反Google的某些设计准则?导航抽屉中的每个元素是否都应该与我期望的处于同一水平?我有想要解决的其他解决方案吗?

5 个答案:

答案 0 :(得分:11)

您不必重写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编辑默认行为不会使其像以前一样工作,每个顶级片段都放在后堆栈上,因此后退按钮将转到所有顶级片段。目前尚不清楚如何将顶级片段作为后堆栈的第一个元素。

答案 1 :(得分:1)

我为这个问题做了一个简单的例子。 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)
}

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

setOf和setDrawerLayout已废弃,应该使用

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

答案 4 :(得分:0)

您可以像这样直接使用目的地的 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) 相同时才有效。 如果有人解释原因,那会很有帮助