欢迎来到第二个关于导航的 MAD Skill 系列 的另一篇文章!本文我们将介绍一个呼声很高的功能,即导航 (Navigation) 对多返回栈的支持。如果您更倾向于视频的形式,请 点击这里 查看视频内容。
概述
假设您的应用使用了 BottomNavigationView
。通过这个功能,当用户选择另一个标签页 (Tab) 时,当前标签页的返回栈会被保存,而所选标签页的返回栈会被恢复。
从 2.4.0-alpha01 版本开始,NavigationUI
辅助类不需要改变任何代码即可支持多返回栈。也就是说,如果您的应用使用了为 BottomNavigationView
或 NavigationView
提供的 setupWithNavController()
方法,则只需要更新依赖库版本,便可默认启用多返回栈。
支持多返回栈
让我们通过这个 仓库 中的高级导航示例来看看实际效果。
该应用由 3 个标签页组成,每个标签页都有它自己的导航流。为了在导航的早期版本中支持多返回栈,我们需要在该示例的 NavigationExtensions 文件中添加一系列辅助函数。通过这些扩展函数,应用可以为每个标签页保持一个单独的 NavHostFragment
,每个 NavHostFragment
带有它自己的返回栈,当用户切换标签页时,应用在不同的 NavHostFragment
之间进行切换。
让我们看看如果移除这些扩展函数会发生什么。为此我删除了 NavigationExtensions
类,在所有使用它的地方都替换为 NavigationUI
中标准的 setupWithNavController()
方法以将我们的 BottomNavigationView
连接到 NavController
上。
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_container
) as NavHostFragment
navController = navHostFragment.navController
// 使用 navController 设置 bottomNavigationView
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)
// 使用 navController 设置 ActionBar 以及 3 个一级目的地页面
appBarConfiguration = AppBarConfiguration(
setOf(R.id.titleScreen, R.id.leaderboard, R.id.register)
)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
toolbar.setupWithNavController(navController, appBarConfiguration)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration)
}
}
同时,我使用 include
标签将 3 个单独的导航图合并为一个图。现在我们的 Activity 布局只包含一个带有单个导航图的 NavHostFragment
。
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@+id/home">
<include app:graph="@navigation/home"/>
<include app:graph="@navigation/list"/>
<include app:graph="@navigation/form"/>
</navigation>
当我运行应用时,这次底部标签页不再保持它们的状态,并会在我切换到其他标签页时重置它的返回栈。由于移除了 NavigationExtensions
,该应用不再支持多返回栈。
现在我将更新 navigation 和 fragment 依赖库的版本。
// fragment 最新版本 https://developer.android.google.cn/jetpack/androidx/releases/fragment?hl=en
// navigation 最新版本 https://developer.android.google.cn/jetpack/androidx/releases/navigation?hl=en
versions.fragment = "1.4.0-alphaXXX"
versions.navigation = "2.4.0-alphaXXX"
Gradle sync 完成后,我再次运行应用,这时当我导航至其他标签页,可以看到每个标签页都保持了它的状态。注意这个行为是默认启用的。
最后,让我们运行测试来验证是否一切正常。该应用已经拥有一些验证多返回栈行为的测试。我运行 BottomNavigationTest 并观察每个底部导航行为测试的运行。
瞧,我们所有测试都通过了!
小结
就是这样!如果您的应用使用 BottomNavigationView
或 NavigationView
,并且您一直在等待支持多返回栈,您所需要做的仅仅是更新 navigation 和 fragment 依赖库,不需要改变任何代码!
如果您需要进一步的自定义,也有新的 API 支持保存和恢复返回栈。请参阅我们之前的推文《Android 多返回栈技术详解》。
如果您想了解更多有关底层 API 以及需要修改哪些内容以支持多返回栈的信息,请参阅我们之前的推文《全新的 Fragment: 使用新的状态管理器》。
感谢您关注本导航系列!
欢迎您 点击这里 向我们提交反馈,或分享您喜欢的内容、发现的问题。您的反馈对我们非常重要,感谢您的支持!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。