背景
Navigation組件是Android X 依賴庫中的一個導航組件,它能接替管理多Fragment之間的關系及跳轉行為,提供一個清晰可見的視圖管理界面來管理整個視圖樹
功能組成
- Navigation Graph 【導航圖定義】
- 作用:用來定義各個Fragment之間的跳轉行為测秸,
- 上圖表示每個Fragment均有自己的ID,同時通過紅色箭頭表示各個Fragment之間的跳轉關系,讓開發(fā)者清楚知道各個頁面之間的關系,開發(fā)過程中可以通過Fragment的ID進行跳轉
- 作用:用來定義各個Fragment之間的跳轉行為测秸,
- NavHostFragment 【導航承載容器】
- 作用:NavHostFragment持有一個FrameLayout,接下來Navigation Graph中的所有Fragment之間的切換都是在該容器內(nèi)完成的
- NavController 【導航跳轉控制器】
- 作用:NavHostFragment在管理頁面時,將頁面之間的控制行為轉交給NavConroller進行處理膳犹,比如控制頁面相互跳轉,或者參數(shù)傳遞签则,頁面返回處理等
功能準備階段
-
導航視圖的申明[Navigation Graph]
- 創(chuàng)建視圖文件至指定目錄下:
app/src/main/res/navigation/xxx_navigation.xml
- 創(chuàng)建視圖根節(jié)點
<navigation
须床,通過app:startDestination="@+id/home_dest"
指定默認顯示的根布局 - 創(chuàng)建視圖子節(jié)點
<fragment
- 通過視圖子節(jié)點的
<action
節(jié)點,定義下一個需要跳轉的頁面渐裂,配置頁面跳轉時的動畫 - 通過視圖子節(jié)點的
<argument
節(jié)點豺旬,定義當前父節(jié)點<fragment
所需要的參數(shù)類型,可以定義多個<argument
節(jié)點 - 通過視圖子節(jié)點的
<deeplink
節(jié)點柒凉,申明外部可以通過deeplink協(xié)議直接跳轉到當前<fragment
上族阅,不需要額外過多的處理
- 通過視圖子節(jié)點的
- 導航視圖的整體節(jié)點圖
<navigation <fragment <action <argument <deeplink
- 創(chuàng)建視圖文件至指定目錄下:
-
導航承載容器的申明[NavHostFragment]
- 在Activity的布局中,申明NavHostFragment膝捞,并關聯(lián) Navgation Graph坦刀,該視圖樹默認顯示的頁面是
<navgation
節(jié)點中的app:startDestination="@+id/home_dest"
對應的fragment
<fragment android:id="@+id/my_nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/mobile_navigation" />
- 在Activity的布局中,申明NavHostFragment膝捞,并關聯(lián) Navgation Graph坦刀,該視圖樹默認顯示的頁面是
基本功能
頁面跳轉 - 兩種方式
- 通過 destinationId的方式跳轉
- 定義
<fragment android:id="@+id/flow_step_one_dest" android:name="com.example.android.codelabs.navigation.FlowStepFragment" tools:layout="@layout/flow_step_one_fragment"/>
- 跳轉邏輯
findNavController().navigate(R.id.flow_step_one_dest)
- 定義
- 通過 actionid的方式跳轉
- 定義
<fragment <action android:id="@+id/next_action" app:destination="@+id/flow_step_one_dest" app:enterAnim="@anim/slide_in_right" app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> </fragment>
- 跳轉邏輯
這時候會找到action對應的destinationid,然后再進行跳轉
view.findViewById<Button>(R.id.navigate_action_button)?.setOnClickListener( Navigation.createNavigateOnClickListener(R.id.next_action, null) )
- 定義
參數(shù)傳遞 - 兩種方式
- 代碼傳遞
val bundle = Bundle() bundle.putString("name", "netease") findNavController().navigate(R.id.flow_step_one_dest, bundle)
- 通過布局文件的argument節(jié)點傳遞數(shù)據(jù)
- 布局文件
<navigation <fragment android:id="@+id/flow_step_two_dest"> <argument android:name="name" android:defaultValue="defaultName" app:argType="string" /> </fragment>
- 代碼傳遞
val args = FlowStepFragmentArgs("netease") findNavController().navigate(R.id.flow_step_two_dest, args.toBundle())
- 布局文件
參數(shù)保存
- 通過ViewModel來保存數(shù)據(jù)
- 在Fragment.onDestoryView中蔬咬,將數(shù)據(jù)保存至Arguments中
進階使用
- deeplink打開指定頁面鲤遥,指定回退的頁面
- 和ToolBar的聯(lián)合使用
存在的坑
- 在進行頁面切換時,需要保證切換前后的兩個頁面都在Navigation Graph中林艘,否者無法獲取NavController對象盖奈,導致頁面切換失敗
- fragment切換的實現(xiàn)是通過replace來完成的,也就是說會銷毀視圖狐援,這里就需要我們自己手動對數(shù)據(jù)進行保存