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」的作法?你怎麼看?

相關文章
相關標籤/搜索