Android Jetpack - 使用 Navigation 管理頁面跳轉(zhuǎn)

在今年的 IO 大會上,發(fā)布了一套叫 Android Jetpack 的程序庫他去。Android Jetpack 里的組件大部分我們都接觸過了,其中也有一些全新的組件,其中一個(gè)就是 Navigation咕幻。

簡介

Navigation 是用來管理 APP 里頁面跳轉(zhuǎn)的。起初顶霞,我以為它是用來代替 startActivity 的肄程,但其實(shí)并不是,大家往下看就知道它的作用了。

另外蓝厌,iOS 的同學(xué)可能會有似曾相識的感覺玄叠,Navigation 應(yīng)該是有借鑒 Storyboard 的。

使用

我們先來看看 Navigation 的實(shí)現(xiàn)過程拓提。

添加依賴

首先诸典,需要使用 Android Studio 3.2 以上版本才能使用 Navigation。

在 build.gradle 中添加依賴:

implementation "android.arch.navigation:navigation-fragment:$nav_version"
implementation "android.arch.navigation:navigation-ui:$nav_version"

創(chuàng)建 navigation xml 文件

使用 「Android Resource File」創(chuàng)建 xml 文件的時(shí)候崎苗,可以看到在類型里狐粱,多了一個(gè) Navigation 的選項(xiàng):

創(chuàng)建成功后,就來到了文章開頭的那個(gè)一個(gè)可視化的操作界面胆数。點(diǎn)擊左上角的添加小圖標(biāo)肌蜻,會出現(xiàn) Activity 和 Fragment,我們這里添加兩個(gè) Activity 和兩個(gè) Fragment:

配置 Action

Fragment 的右邊有個(gè)小圓圈必尼,點(diǎn)擊并拖到另一個(gè)頁面蒋搜,這樣我們就給這個(gè) Fragment 添加了一個(gè)跳轉(zhuǎn)行為,也就是 Action判莉。

但是可以發(fā)現(xiàn)豆挽,Activity 的右邊是沒有這個(gè)小圓圈的,所以 Navigation 并不能處理從 Activity 發(fā)起的跳轉(zhuǎn)帮哈。

左上角有個(gè)小房子的是顯示的第一個(gè)頁面,但由于 Activity 無法發(fā)起跳轉(zhuǎn)锰镀,所以這里把 MainActivity 刪除娘侍,把 MainFragment 作為主頁面,并給它添加跳轉(zhuǎn)到 SecondFragment 和 SecondActivity 的 Action:

自動(dòng)生成的 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

現(xiàn)在泳炉,我們第一個(gè)頁面是 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>

其中有三個(gè)屬性需要注意花鹅。使用 android:name 指定 Fragment 的類型為 NavHostFragment氧腰,使用 app:navGraph 指定 Navigation 文件。app:defaultNavHost="true" 的作用是刨肃,讓 Navigation 處理返回事件古拴,點(diǎn)返回按鈕時(shí)并不是返回上一個(gè) Activity,而是返回上一個(gè)「頁面」之景,上一個(gè)「頁面」有可能是 Activity斤富,也可能是 Fragment。

至此锻狗,Navigation 的簡單配置就算完成了满力,接下來看如何使用它焕参。

配置跳轉(zhuǎn)

在 Navigation 里,頁面的跳轉(zhuǎn)是交給 NavController 來處理的油额,獲取 NavController 的方法有這么三種:

NavHostFragment.findNavController(Fragment)
Navigation.findNavController(Activity, @IdRes int viewId)
Navigation.findNavController(View)

拿到后叠纷,通過 navigate 方法,通過傳入 Action 的 id潦嘶,實(shí)現(xiàn)跳轉(zhuǎn)涩嚣,比如:

NavHostFragment
            .findNavController(this)
            .navigate(R.id.action_firstFragment_to_secondFragment)

在簡單配置了兩個(gè)跳轉(zhuǎn)后,看一下目前的效果:

傳參

頁面的跳轉(zhuǎn)少不了數(shù)據(jù)的傳遞掂僵,使用 Navigation航厚,和我們原來的跳轉(zhuǎn)一樣,可以通過 Bundle 來傳遞參數(shù):

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

如果跳轉(zhuǎn)到 Activity锰蓬,可以從 intent.extras 獲取到 bundle幔睬,如果是 Fragment,則從 arguments 獲取到芹扭。

此外麻顶,還可以在 Navigation 的 xml 文件中配置傳參,但這種方式目前支持的數(shù)據(jù)類型比較少舱卡,連 boolean 都不支持辅肾,而且我還碰到了 bug,所以目前不建議用轮锥。

轉(zhuǎn)場動(dòng)畫

如果需要自定義的頁面轉(zhuǎn)場動(dòng)畫矫钓,使用 Navigation 可以很方便的實(shí)現(xiàn)。

這里舉個(gè)例子交胚,比如我們需要一個(gè)從右向左切入的過場動(dòng)畫份汗,先創(chuàng)建這個(gè)動(dòng)畫的 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 的可視化編輯頁面來,點(diǎn)擊跳轉(zhuǎn)的線蝴簇,右邊會出現(xiàn)過場動(dòng)畫的配置選項(xiàng),將 xxxx 設(shè)為剛才創(chuàng)建的動(dòng)畫:

這么簡單就搞定了匆帚,效果如下:

Navigation 的使用介紹就到這里熬词。

思考

你可能已經(jīng)明白,Navigation 主要是用來處理 Fragment 的跳轉(zhuǎn)吸重,所以說它并不是用來代替 startActivity互拾,而是用來代替 FragmentTransaction 的相關(guān)操作。

在官方文檔里嚎幸,可以看到一個(gè)將傳統(tǒng)跳轉(zhuǎn)遷移到 Navigation 的建議颜矿。我簡單理解為,將原本兩個(gè) Activity 之間的跳轉(zhuǎn)嫉晶,逐漸修改為使用一個(gè) Activity 作為容器骑疆,用兩個(gè) Fragment 作為頁面跳轉(zhuǎn)田篇。

看到這里,我聯(lián)想到了在去年箍铭,Jake Wharton(目前在谷歌)有這么一個(gè)有爭議的言論:

“一個(gè) APP 只需要一個(gè) Activity泊柬。”

在過去诈火,要實(shí)現(xiàn)這種方式兽赁,就需要去解決復(fù)雜的 Fragment 堆棧處理,而且早期的 Fragment 坑比較多冷守,處理不好容易出現(xiàn)頁面穿透等問題〉堆拢現(xiàn)在 Navigation 恰好解決了這些問題。

這一切聯(lián)系起來拍摇,是不是能說明官方間接支持了「少用 Activity 多用 Fragment」的做法亮钦?你怎么看?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末授翻,一起剝皮案震驚了整個(gè)濱河市或悲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堪唐,老刑警劉巖巡语,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異淮菠,居然都是意外死亡男公,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門合陵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枢赔,“玉大人,你說我怎么就攤上這事拥知√ぐ荩” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵低剔,是天一觀的道長速梗。 經(jīng)常有香客問我,道長襟齿,這世上最難降的妖魔是什么姻锁? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮猜欺,結(jié)果婚禮上位隶,老公的妹妹穿的比我還像新娘。我一直安慰自己开皿,他們只是感情好涧黄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布篮昧。 她就那樣靜靜地躺著,像睡著了一般弓熏。 火紅的嫁衣襯著肌膚如雪恋谭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天挽鞠,我揣著相機(jī)與錄音疚颊,去河邊找鬼。 笑死信认,一個(gè)胖子當(dāng)著我的面吹牛材义,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嫁赏,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼其掂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潦蝇?” 一聲冷哼從身側(cè)響起款熬,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎攘乒,沒想到半個(gè)月后贤牛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡则酝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年殉簸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沽讹。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡般卑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出爽雄,到底是詐尸還是另有隱情蝠检,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布挚瘟,位于F島的核電站蝇率,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏刽沾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一排拷、第九天 我趴在偏房一處隱蔽的房頂上張望侧漓。 院中可真熱鬧,春花似錦监氢、人聲如沸布蔗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纵揍。三九已至顿乒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間泽谨,已是汗流浹背璧榄。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吧雹,地道東北人骨杂。 一個(gè)月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像雄卷,于是被迫代替她去往敵國和親搓蚪。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容