这是第二个关于导航 (Navigation) 的 MAD Skills 系列,如果您想回顾过去发布的内容,请参考下面链接查看:
今天为大家发布本系列文章中的第一篇。在本文中,我们将为大家讲解另外一个用例,即类似操作栏 (Action Bar)、底部标签栏或者抽屉型导航栏之类的 UI 组件如何在应用中实现导航功能。如果您更倾向于观看视频而非阅读文章,请查看 视频 内容。
概述
在之前的 导航系列文章 中, Chet 开发了一个用于 跟踪甜甜圈的应用 。知道什么是甜甜圈的最佳搭档吗?(难道是另一个甜甜圈?) 当然是咖啡!所以我准备增加一个追踪咖啡的功能。我需要在应用中增加一些页面,所以有必要使用抽屉式导航栏或者底部标签栏来辅助用户导航。但是我们该如何使用这些 UI 组件来集成导航功能呢?通过点击监听器手动触发导航动作吗?
不需要!无需任何监听器。NavigationUI 类通过匹配目标页面 id 与菜单 id 实现不同页面之间的导航功能。让我们深入探索一下它的内部机制吧。
添加咖啡追踪器
△ 工程结构
首先我将与甜甜圈相关的类文件拷贝了一份到新的包下,并且将它们重命名。这样的操作对于真正的应用来说也许不是最好的做法,但是在这里可以快速帮助我们添加咖啡跟踪功能到已有的应用中。如果您希望随着文章内容同步操作,可以获取 这里的代码 ,里面包含了全部针对 Donut Tracker 应用的修改,可以基于该代码了解 NavigationUI。
基于上面所做的修改,我更新了导航图,新增了从 coffeeFragment 到 coffeeDialogFragment 以及从 selectionFragment 到 donutFragment 相关的目的页面和操作。之后我会用到这些目的页面的 id ;)
△ 带有新的目的页面的导航图
更新导航图之后,我们可以开始将元素绑定起来,并且实现导航到 SelectionFragment。
选项菜单
应用的选项菜单现在尚未发挥作用。要启用它,需要在
onOptionsItemSelected()
函数中,为被选择的菜单项调用
onNavDestinationSelected()
函数,并传入
navController
。只要目的页面的
id
和
MenuItem
的 id 相匹配,该函数会导航到绑定在
MenuItem
上的目的页面。
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return item.onNavDestinationSelected(
findNavController(R.id.nav_host_fragment)
) || super.onOptionsItemSelected(item)
}
复制代码
现在导航控制器可以 "支配" 菜单项了,我将
MenuItem
的
id
与之前所创建的目的页面的
id
进行了匹配。这样,导航组件就可以将
MenuItem
与目的页面进行关联。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.android.samples.donuttracker.MainActivity">
<item
android:id="@+id/selectionFragment"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>
复制代码
Toolbar
现在应用可以导航到
selectionFragment
,但是标题仍然保持原样。当处于
selectionFragment
的时候,我们希望标题可以被更新并且显示返回按钮。
首先我需要添加一个
AppBarConfiguration
对象,
NavigationUI
会使用该对象来管理应用左上角的导航按钮的行为。
appBarConfiguration = AppBarConfiguration(navController.graph)
复制代码
该按钮会根据您的目的页面的层级改变自身的行为。比如,当您在最顶层的目的页面时,就不会显示回退按钮,因为没有更高层级的页面。
默认情况下,您应用的最初页面是唯一的最顶层目的页面,但是您也可以定义多个最顶层目的页面。比如,在我们的应用中,我可以将 donutList 和 coffeeList 的目的页面都定义为最顶层的目的页面。
接下来,在
MainActivity
类中,获得
navController
和
toolbar
的实例,并且验证
setSupportActionBar()
是否被调用。这里我还更新了传入函数的 toolbar 的引用。
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_fragment
) as NavHostFragment
navController = navHostFragment.navController
val toolbar = binding.toolbar
复制代码
要在默认的操作栏 (Action Bar) 中添加导航功能,我在这里使用了
setupActionBarWithNavController()
函数。该函数需要两个参数:
navController
和
appBarConfiguration
。