具有多个顶级目的地的导航图
Navigation graph with multiple top level destinations
我在空闲时间实现了一个 android 应用程序(在 Kotlin 中,但这与问题无关),我尝试使用 android jetpack 和新库。我有一个带导航抽屉的 Activity。我尽量按照sample sunflower app。它在主要 activity 中使用以下组合来启用导航抽屉背后的逻辑:
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
覆盖为 return 来相当轻松地解决该问题] 与导航图的起始目的地不同的顶级目的地。
但是我的问题是,为什么会有这种默认行为?这是一个错误吗?如果我覆盖它,我是否会违反 Google 的一些设计指南?导航抽屉中的每个元素不应该像我期望的那样处于同一水平吗?是否有针对我想做的事情的不同解决方案?
您不必重写 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 编辑默认行为不会使其行为像以前一样,每个顶级片段都放在后退堆栈上,因此后退按钮将转到所有顶级片段。目前尚不清楚如何将顶级片段作为返回堆栈的第一个元素。
我针对这个问题做了一个简单的例子。
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)
}
要获得具有多个顶级目标的工具栏和抽屉的正确行为,您可以使用以下代码:
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
setOf 和 setDrawerLayout 已删除,您应该使用
AppBarConfiguration 配置=新AppBarConfiguration.Builder(R.id.defaultFragment,R.id.firstFragment,R.id.secondFragment).setOpenableLayout(drawerLayout).build();
您可以像这样直接使用目的地的 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) 相同时它才会起作用。
如果有人解释为什么会这样,那将是很大的帮助
我在空闲时间实现了一个 android 应用程序(在 Kotlin 中,但这与问题无关),我尝试使用 android jetpack 和新库。我有一个带导航抽屉的 Activity。我尽量按照sample sunflower app。它在主要 activity 中使用以下组合来启用导航抽屉背后的逻辑:
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
覆盖为 return 来相当轻松地解决该问题] 与导航图的起始目的地不同的顶级目的地。
但是我的问题是,为什么会有这种默认行为?这是一个错误吗?如果我覆盖它,我是否会违反 Google 的一些设计指南?导航抽屉中的每个元素不应该像我期望的那样处于同一水平吗?是否有针对我想做的事情的不同解决方案?
您不必重写 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 编辑默认行为不会使其行为像以前一样,每个顶级片段都放在后退堆栈上,因此后退按钮将转到所有顶级片段。目前尚不清楚如何将顶级片段作为返回堆栈的第一个元素。
我针对这个问题做了一个简单的例子。 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)
}
要获得具有多个顶级目标的工具栏和抽屉的正确行为,您可以使用以下代码:
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
setOf 和 setDrawerLayout 已删除,您应该使用
AppBarConfiguration 配置=新AppBarConfiguration.Builder(R.id.defaultFragment,R.id.firstFragment,R.id.secondFragment).setOpenableLayout(drawerLayout).build();
您可以像这样直接使用目的地的 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) 相同时它才会起作用。 如果有人解释为什么会这样,那将是很大的帮助