我在业余时间实现了一个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的某些设计准则?导航抽屉中的每个元素是否都应该与我期望的处于同一水平?我有想要解决的其他解决方案吗?
答案 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) 相同时才有效。 如果有人解释原因,那会很有帮助