零、引

2018年Google I/O开发者大会上,随着Android P的发布,同时也面向开发者发布了被Google称之为下一代安卓组件的Android Jetpack,它能够免去开发者编写样板代码的麻烦,为开发助力。 而一起发布的Android Studio3.2(金丝雀)也同步支持了Jetpack组件开发并提供了相应可视化开发工具。

而Navigation,导航组件正是包含在Jetpack中,其主要作用是取代Fragment管理器,通过更加简单易懂的方式实现实现不同Fragment之间的跳转。

一、框架创建

Jetpack功能强烈依赖于Android Studio,因此如果想使用,则需要先下载Android Studio3.2以上的版本进行开发。

一般来说,我们通过Android Studio通过模板创建一个Basci Activity项目,其中就会包含完整的导航框架。如果对于一个已有项目,我们想向其中添加导航功能,则需要向Gradle配置build.gradle中添加相应依赖:

dependencies {
  def nav_version = "2.4.2"

  // 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:$nav_version"
}

 二、框架的使用

一般,对于导航框架,有着三个必要要素:

  1. Navigation graph,即nav_graph,一个用于保存全部导航信息的XML资源文件
  2. NavHostFragment,一个特殊的Fragment,用于装载导航内容
  3. NavController,导航控制器,用于管理导航对象,实现Fragment间跳转

首先,需要创建nav_graph导航资源,需要在res/navigation中创建nav_graph.xml文件,或者,如果,正在使用Android Studio3.3以上版本,还可以直接在res上右键选择New -> Android Resource Directory,在Resource type中选择Navigation,如下图。
1651195055981.png

然后,需要创建NavHostFragment容器,我们一般可以在需要放置Fragment的Activity上创建该Fragment,即

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <fragment
        android:id="@+id/nav_host_fragment_content_main"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

其中,

android:name="androidx.navigation.fragment.NavHostFragment"

是指定该Fragment为NavHostFragment,该组件用于装载Fragment,

app:navGraph="@navigation/nav_graph"

则指定该NavHostFragment使用nav_graph资源文件来进行导航。

最后,我们在Activity中创建导航控制器,就可以进行Fragment之间的导航切换。

NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);

以上代码均来自Android Studio的默认模板,需要完整代码可自行创建相应的模板。

三、导航切换

接下来,我们可以对nav_graph进行编写来实现导航间的切换,首先,我们来看一下示例代码

<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
    android:id="@+id/nav_graph"
    app:startDestination="@id/FirstFragment">

    <fragment
        android:id="@+id/FirstFragment"
        android:name="com.utopiaxc.test.FirstFragment"
        android:label="@string/first_fragment_label"
        tools:layout="@layout/fragment_first">

        <action
            android:id="@+id/action_FirstFragment_to_SecondFragment"
            app:destination="@id/SecondFragment" />
    </fragment>
    <fragment
        android:id="@+id/SecondFragment"
        android:name="com.utopiaxc.test.SecondFragment"
        android:label="@string/second_fragment_label"
        tools:layout="@layout/fragment_second">

        <action
            android:id="@+id/action_SecondFragment_to_FirstFragment"
            app:destination="@id/FirstFragment" />
    </fragment>
</navigation>

我们可以看到,navigation是这个XML文件的根节点,其中,我们可以添加fragment标签,或者,也可以添加activity标签作为导航终点。这里需要注意的是,导航起点必须为Fragment,而终点则不加限制,这是因为导航是基于Fragment视图使用的,起点不能脱离Fragment。

然后,我们希望在已注册的Fragment或Activity间进行跳转,则需要在起点Fragment中添加action标签,action标签必须包含目的地ID,即

app:destination="@id/DestinationFragment"

,同时,必须给予自身一个ID用于使用该导航,如上示例代码中,第一个Fragment中的action,就是可以通过id为action_FirstFragment_to_SecondFragment的导航从该Fragment导航到id为SecondFragment的Fragment。

在Android Studio中,同样也提供了可视化的导航编辑器,这更加直观地体现了不同Fragment间的关系。

1651196431005.png

最后,我们在对应Fragment的代码中使用NavController导航控制器的静态类方法就可以完成导航切换。

NavHostFragment.findNavController(FirstFragment.this)
        .navigate(R.id.action_FirstFragment_to_SecondFragment);

四、补充

其实,导航组件不仅支持最简单的Fragment跳转,还支持很多其他功能,在此就不多赘述,感兴趣的可以深入地了解其中的原理。

 五、参考

[1] Google.Android 开发者-文档-指南-导航.2021/10/27

[2] 谷歌开发者.导航组件概览 | MAD Skills.2021/02/04

[3] 37手游安卓团队.安卓navigation系列——入门篇.2020/11/23

本篇内容为原创内容,采用CC BY-NC-SA 4.0协议许可
2022-04-29 09:54
UtopiaXC
于大连


尽管如此,世界依旧美丽