Android Jetpack - 使用 Navigation 管理页面跳转

在今年的 IO 大会上,发布了一套叫 Android Jetpack 的程序库。Android Jetpack 里的组件大部分咱们都接触过了,其中也有一些全新的组件,其中一个就是 Navigation。php

简介

Navigation 是用来管理 APP 里页面跳转的。起初,我觉得它是用来代替 startActivity 的,但其实并非,你们往下看就知道它的做用了。java

另外,iOS 的同窗可能会有似曾相识的感受,Navigation 应该是有借鉴 Storyboard 的。android

使用

咱们先来看看 Navigation 的实现过程。app

添加依赖

首先,须要使用 Android Studio 3.2 以上版本才能使用 Navigation。ide

在 build.gradle 中添加依赖:布局

implementation "android.arch.navigation:navigation-fragment:$nav_version"
implementation "android.arch.navigation:navigation-ui:$nav_version"
复制代码

建立 navigation xml 文件

使用 「Android Resource File」建立 xml 文件的时候,能够看到在类型里,多了一个 Navigation 的选项:gradle

建立成功后,就来到了文章开头的那个一个可视化的操做界面。点击左上角的添加小图标,会出现 Activity 和 Fragment,咱们这里添加两个 Activity 和两个 Fragment:动画

配置 Action

Fragment 的右边有个小圆圈,点击并拖到另外一个页面,这样咱们就给这个 Fragment 添加了一个跳转行为,也就是 Action。ui

可是能够发现,Activity 的右边是没有这个小圆圈的,因此 Navigation 并不能处理从 Activity 发起的跳转。this

左上角有个小房子的是显示的第一个页面,但因为 Activity 没法发起跳转,因此这里把 MainActivity 删除,把 MainFragment 做为主页面,并给它添加跳转到 SecondFragment 和 SecondActivity 的 Action:

自动生成的 xml 代码是这样的:

<?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" app:startDestination="@id/mainFragment">

    <fragment android:id="@+id/mainFragment" android:name="com.example.navigation.MainFragment" android:label="fragment_main" tools:layout="@layout/fragment_main">
        <action android:id="@+id/action_mainFragment_to_secondFragment" app:destination="@id/secondFragment" app:enterAnim="@anim/slide_in_right" />
        <action android:id="@+id/action_mainFragment_to_secondActivity" app:destination="@id/secondActivity" />
    </fragment>
    <fragment android:id="@+id/secondFragment" android:name="com.example.navigation.SecondFragment" android:label="fragment_second" tools:layout="@layout/fragment_second" />
    <activity android:id="@+id/secondActivity" android:name="com.example.navigation.SecondActivity" android:label="activity_second" tools:layout="@layout/activity_second" />

</navigation>
复制代码

布局中添加 Fragment

如今,咱们第一个页面是 MainFragment,而 Fragment 须要 Activity 做为容器,修改 MainActivity 的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">

    <fragment android:id="@+id/fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav" />

</FrameLayout>
复制代码

其中有三个属性须要注意。使用 android:name 指定 Fragment 的类型为 NavHostFragment,使用 app:navGraph 指定 Navigation 文件。app:defaultNavHost="true" 的做用是,让 Navigation 处理返回事件,点返回按钮时并非返回上一个 Activity,而是返回上一个「页面」,上一个「页面」有多是 Activity,也多是 Fragment。

至此,Navigation 的简单配置就算完成了,接下来看如何使用它。

配置跳转

在 Navigation 里,页面的跳转是交给 NavController 来处理的,获取 NavController 的方法有这么三种:

NavHostFragment.findNavController(Fragment)
Navigation.findNavController(Activity, @IdRes int viewId)
Navigation.findNavController(View)
复制代码

拿到后,经过 navigate 方法,经过传入 Action 的 id,实现跳转,好比:

NavHostFragment
            .findNavController(this)
            .navigate(R.id.action_firstFragment_to_secondFragment)
复制代码

在简单配置了两个跳转后,看一下目前的效果:

传参

页面的跳转少不了数据的传递,使用 Navigation,和咱们原来的跳转同样,能够经过 Bundle 来传递参数:

val bundle = Bundle()
bundle.putString("name", "SouthernBox")
NavHostFragment
            .findNavController(this)
            .navigate(R.id.action_firstFragment_to_secondFragment, bundle)
复制代码

若是跳转到 Activity,能够从 intent.extras 获取到 bundle,若是是 Fragment,则从 arguments 获取到。

此外,还能够在 Navigation 的 xml 文件中配置传参,但这种方式目前支持的数据类型比较少,连 boolean 都不支持,并且我还碰到了 bug,因此目前不建议用。

转场动画

若是须要自定义的页面转场动画,使用 Navigation 能够很方便的实现。

这里举个例子,好比咱们须要一个从右向左切入的过场动画,先建立这个动画的 xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <translate android:duration="600" android:fromXDelta="100%" android:toXDelta="0" />

</set>
复制代码

而后咱们回到 Navigation 的可视化编辑页面来,点击跳转的线,右边会出现过场动画的配置选项,将 xxxx 设为刚才建立的动画:

这么简单就搞定了,效果以下:

Navigation 的使用介绍就到这里。

思考

你可能已经明白,Navigation 主要是用来处理 Fragment 的跳转,因此说它并非用来代替 startActivity,而是用来代替 FragmentTransaction 的相关操做。

在官方文档里,能够看到一个将传统跳转迁移到 Navigation 的建议。我简单理解为,将本来两个 Activity 之间的跳转,逐渐修改成使用一个 Activity 做为容器,用两个 Fragment 做为页面跳转。

看到这里,我联想到了在去年,Jake Wharton(目前在谷歌)有这么一个有争议的言论:

“一个 APP 只须要一个 Activity。”

在过去,要实现这种方式,就须要去解决复杂的 Fragment 堆栈处理,并且早期的 Fragment 坑比较多,处理很差容易出现页面穿透等问题。如今 Navigation 刚好解决了这些问题。

这一切联系起来,是否是能说明官方间接支持了「少用 Activity 多用 Fragment」的作法?你怎么看?

相关文章
相关标签/搜索