Navigation组件
Navigation组件旨在实现单Activity,多Fragment的应用场景。它是会帮助你自动实现Android定义的导航原则的组件;
导航原则是什么呢?
导航原则
导航原则是Android规定的有关应用内以及不同应用间跳转的规则。这是为了使用户的在桌面、应用内、应用间的跳转操作有一致性,使Andorid系统操作规范起来的规则。
导航原则要求:
1、固定的‘首页’
每个App有一个界面作为固定的起点和终点。即我们俗称的首页,打开App第一眼看到的页面和退出App前看到的最后一个页面必须是同一个。
注释:Google官方似乎不把登录界面、启动页看作用户打开的第一个界面。关于登录界面,他们的解释是【应用可能会有一次性设置或一系列登录屏幕。不应将这些条件屏幕视为起始目的地,因为用户只有在特定情况下才会看到这些屏幕。】但是关于启动页(如打开网易云音乐App时,会显示网易云Logo以及广告页那一些界面),并没有对此做明确的解释。
2、堆栈管理
返回堆栈:每个应用都有独立的返回堆栈。和以前的Activity堆栈几乎一样,起始页在堆栈底部,堆栈顶部就是当前界面。只不过这次Fragment也在堆栈中了。(这一段属于我的个人推测,因为是学习笔记嘛= =)
3、两种返回按钮
官方特地提到了,返回按钮分两种。一种是系统底部导航栏的返回按钮,我简称之系统返回按钮;一种是在应用内,一般位于屏幕顶部,被放置在标题左边的返回按钮,我简称之应用内返回按钮。简单来说,系统返回按钮能退出应用。而应用内返回按钮理论上不可以用来退出应用。官方甚至建议,首页不应出现应用内返回按钮。
展开:上述两个按钮在深层链接(应用间跳转)的时候,区别较为明显,有不同的功能。举例子:当用户从应用A跳转到应用B的时候,用户点击系统返回按钮,会返回到应用A。而用户点击应用内返回按钮则会跳转到应用B内的上一个界面。
这里还涉及到一个深层链接的概念,我目前的需求似乎不需要理解这个东西。先留一个坑,以后有时间再展开细说。
Navigation组件使用
1、添加依赖
dependencies {
def nav_version = "2.3.1"
// Java language implementation
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
// Kotlin
//implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
//implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
// Feature module Support
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
// Testing Navigation
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
// Jetpack Compose Integration
implementation "androidx.navigation:navigation-compose:1.0.0-alpha01"
}
2、创建导航图
导航图是一个xml资源文件。它表示各个界面间的跳转路线。Android Studio提供了窗口,使得我们可以直观的看到导航的具体情况。在该资源文件中,我们定义了起始目的地,可以认为那就是我们的首页了;此外,我们还定义了各个界面(fragment)可以前往的其他界面,他们之间所建立的单向通道通过action字段来定义。
添加方法以后再做描述。目前具体方法参照
3、为Activity添加NavHost
NavHost,官方翻译为导航宿主。
关于他的定义,我对官方的描述感到困惑:”导航宿主是一个空容器,用户在您的应用中导航时,目的地会在该容器中交换进出。“ 我不清楚所谓的”交换进出“是什么意思,我姑且认为,NavHost作为一个核心部分,Navigation组件通过它 管理界面的交替(显示、隐藏,创建、销毁,进栈、出栈,等不同层次间的行为。)
添加方法有两种,一种直接在界面的布局文件中添加控件、一种通过Android Studio的Layout Editor窗口添加。具体方法以后再描述,目前具体方法参照
注意:Navigation组件旨在实现单Activity,多Fragment的场景。而在多个Activity的应用中,每个Activity都有独自的NavHost,及其对应的导航图。
4、创建目的地 (Destination)
所谓目的地,具体指Activity、Fragment。导航图文件就是描述各个目的地之间的路线的文件。
我们要将目的地(Fragment)添加到导航图中,两种方法。一种是直接编辑xml文件,一种是通过Android Studio提供的Navigation Editor窗口实现(直接点击New Destination 按钮即可)。我们不仅可以添加现有的Fragment、Activity,还可以使用占位符,待新界面实现后再替换过来。
5、设置起始目的地(Start Destination)
起始目的地,即该导航的首页。如第三点所述,每个Activity有自己的导航图。而这就代表了,一旦跳转至Activity,根据该Activity的导航图,它第一个显示的界面就是起始目的地。
**注意:**起始目的地不可以是该导航Activity本身。
6、通过操作(Action)连接各个目的地
官方文档将action翻译成”操作“。而action标签在导航图中用来表示从一个目的地前往另一个目的地的”路线“。它被包含在起点目的地的子属性中,用来表示起点目的地所能前往的其他目的地。
连接操作出了通过直接编辑xml文件外,同样可以通过Navigation Editor窗口去编辑,操作简单,仅需鼠标拖动即可。
7、导航到目的地
做到第六步,我们的导航图已经构建完成。接下里便是具体的使用。要实现界面的跳转,我们需要从NavHost(NavHostFragment)从获取到NavController对象,执行他的navigate()方法。
获取NavController代码如下:
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_nav);
NavController navController = navHostFragment.getNavController();
在获取到NavController后,执行nagivate跳转操作。在这里,官方推荐了Safe Args插件;该插件很方便,会自动生成对应的action代码,无需自己再去编辑对应代码。
使用Safe Args插件的跳转代码如下:
NavDirections action = TestFragmentDirections.actionTestFragmentToTest2Fragment();
navController.navigate(action);
这里的TestFragmentDirections类,以及他的方法actionTestFragmentToTest2Fragment(),由Sage Args插件生成。而其中,TestFragment、Test2Fragment类是我所创建的Fragment类。而创建的Action连接,是从TestFragment 跳转至 Test2Fragment。