Navigation 直接翻譯即為導(dǎo)航,它是 Android Jetpack 組件之一箕速,讓單 Activity 應(yīng)用成為首選架構(gòu)躁染。應(yīng)用內(nèi)Fragment頁面的跳轉(zhuǎn)則由 Navigation 來處理城看,開發(fā)者無需在處理 FragmentTransaction 的復(fù)雜性以及相關(guān)的轉(zhuǎn)場動畫。
相比之前Fragment的管理需要借助FragmentManager和FragmentTransaction,使用Navigation組件有如下一些優(yōu)點:
1.可視化的頁面導(dǎo)航圖恐锣,方便我們理清頁面之間的關(guān)系
2.通過destination和action完成頁面間的導(dǎo)航
3.方便添加頁面切換動畫
4.頁面間類型安全的參數(shù)傳遞
5.通過Navigation UI類夹囚,對菜單/底部導(dǎo)航/抽屜藍(lán)菜單導(dǎo)航進行統(tǒng)一的管理
實戰(zhàn)完成效果
使用Navigation
1. 引入依賴
在app的gradle.build中添加依賴:
nav_version=2.5.0
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
2. 了解組成
Navigation graph
一個包含所有導(dǎo)航相關(guān)信息的 XML 資源
xml 檔,包含所有被管理的 Fragment穴翩,起始目標(biāo)犬第,換頁目標(biāo),返回目標(biāo)芒帕。NavHostFragment
一種特殊的Fragment歉嗓,用于承載導(dǎo)航內(nèi)容的容器NavController
用來管理 NavHost 中的導(dǎo)航動作,通常是寫在點擊事件內(nèi)完成 Fragment 的切換副签。
findNavController().navigate(R.id.action_Fragment1_to_Fragment2)
3.開始接入
1.右鍵res遥椿,點擊New -> Android Resource Directory
2.在出現(xiàn)的面板第二行Resource type 下拉列表中選擇 Navigation,然后點擊 OK
3.res目錄下會多出一個navigation的資源目錄淆储,右鍵該目錄冠场,點擊New -> Navigation Resource File,輸入需要新建的資源文件名本砰,這里命名nav_graph碴裙,點擊ok,一個nav_graph.xml就創(chuàng)建好了。
新建好的nav_graph.xml切換到design模式下舔株,點擊2處的加號莺琳,選擇Create new destination,即可快速創(chuàng)建新的Fragment载慈〔训龋或者直接引用已有的fragment做管理。
建好后办铡,可通過手動配置頁面之間的跳轉(zhuǎn)關(guān)系辞做,點擊某個頁面,右邊會出現(xiàn)一個小圓點寡具,拖曳小圓點指向跳轉(zhuǎn)的頁面秤茅,這里設(shè)置跳轉(zhuǎn)的關(guān)系為FragmentA -> FragmentB。
<?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"
android:id="@+id/nav_graph"
app:startDestination="@id/navigation_home">
<fragment
android:id="@+id/navigation_home"
android:name="com.example.flowmvihilt.ui.main.MainFragment">
<action android:id="@+id/action_to_artical"
app:destination="@id/articalFragment"/>
</fragment>
<fragment
android:id="@+id/navigation_qa"
android:name="com.example.flowmvihilt.ui.main.MainFragment" />
<fragment
android:id="@+id/navigation_system"
android:name="com.example.flowmvihilt.ui.main.MainFragment"
android:label="MainFragment" />
<fragment
android:id="@+id/navigation_mine"
android:name="com.example.flowmvihilt.mine.MeFragment"/>
<fragment
android:id="@+id/articalFragment"
android:name="com.example.flowmvihilt.mine.ArticalFragment"/>
</navigation>
navigation是根標(biāo)簽童叠,通過startDestination配置默認(rèn)啟動的第一個頁面框喳,這里配置的是FragmentA
fragment標(biāo)簽代表一個fragment,其實這里不僅可以配置fragment厦坛,也可以配置activity五垮,甚至還可以自定義
action標(biāo)簽定義了頁面跳轉(zhuǎn)的行為,相當(dāng)于上圖中的每條線粪般,destination定義跳轉(zhuǎn)的目標(biāo)頁拼余,還可以定義跳轉(zhuǎn)時的動畫等等
當(dāng)調(diào)用到 action_FragmentA_to_FragmentB2 這個 action,會從 FragmentA -> FragmentB
在Activity的布局文件中配置NavHostFragment和BottomNavigationView
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:itemBackground="@null"
app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
android:name指定NavHostFragment
app:navGraph指定導(dǎo)航視圖亩歹,即建好的nav_graph.xml
app:defaultNavHost=true意思是可以攔截系統(tǒng)的返回鍵匙监,按返回鍵可以回到上一個頁面
menu文件:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:icon="@drawable/ic_launcher_foreground"
android:title="@string/home_page" />
<item
android:id="@+id/navigation_qa"
android:icon="@drawable/ic_launcher_foreground"
android:title="@string/q_a" />
<item
android:id="@+id/navigation_system"
android:icon="@drawable/ic_launcher_foreground"
android:title="@string/system" />
<item
android:id="@+id/navigation_mine"
android:icon="@drawable/ic_launcher_foreground"
android:title="@string/mine" />
</menu>
將Navigation與BottomNavigationView關(guān)聯(lián)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navView.setupWithNavController(navHostFragment.findNavController())
通過NavController 管理fragment之間的跳轉(zhuǎn)
findNavController().navigate(R.id.action_to_artical)
navigate方法傳入配置的某個action來進行跳轉(zhuǎn)。
跳轉(zhuǎn)傳遞參數(shù)
var args = Bundle()
args.putString("params", "params")
Navigation.findNavController(btnHome).navigate(R.id.fragment_home_to_fragment_msg, args)
目標(biāo)頁接收參數(shù):
var params = arguments?.getString("params")
導(dǎo)航文件拆分
如果項目越來越大小作,頁面越來越多亭姥,所有的都放在一個文件中會非常的臃腫,當(dāng)Action非常復(fù)雜的時候會非常的混亂顾稀。那么可創(chuàng)建多個navigation.xml進行導(dǎo)航达罗。
Deeplink導(dǎo)航
Navigation也能通過Deeplink進行跳轉(zhuǎn)。如下:
findNavController().navigate(Uri.parse("schema://webview.fragment"))
參考:
https://blog.csdn.net/JMW1407/article/details/125714708
https://blog.csdn.net/lcl130/article/details/108422026