一、Navigation 引入
Android 開發(fā)中 , 最常用的 UI 架構(gòu) 就是 使用一個 Activity 嵌套多個 Fragment , 這就需要 對 Fragment 進(jìn)行管理 ;
在傳統(tǒng)的 Android 開發(fā)中 , 使用 FragmentManager 和 FragmentTransaction 管理
- Fragment 的生命周期 ,
- Fragment 頁面切換 ,
- Fragment 切換動畫設(shè)置運(yùn)行 ,
- Fragment 與 Fragment / Activity 之間的數(shù)據(jù)傳遞 ,
- 應(yīng)用 App Bar 管理
等操作 ;
上述操作都是 使用純代碼方式進(jìn)行實(shí)現(xiàn) , 在頁面和 App Bar 管理過程中使用比較繁瑣 , 維護(hù)難度較大 ;
Jetpack 提供的 Navigation 組件 , 解決上述 Fragment 頁面管理 與 App Bar 管理 問題 ;
Navigation 主要功能就是幫助 Activity 管理 Fragment ;
App Bar 是應(yīng)用程序頂部的一個可用于導(dǎo)航和操作應(yīng)用程序的界面元素。App Bar 管理指的是使用 Android 框架提供的 API,對 App Bar 進(jìn)行創(chuàng)建、設(shè)置和管理的過程。
常見的App Bar 管理操作:
- 創(chuàng)建 App Bar:使用 Android 框架提供的 Toolbar 控件創(chuàng)建 App Bar。
- 設(shè)置 App Bar 標(biāo)題:使用 setTitle() 方法設(shè)置 App Bar 的標(biāo)題。
- 設(shè)置 App Bar Logo:使用 setLogo() 方法設(shè)置 App Bar 的 Logo。
- 添加菜單項(xiàng):使用 onCreateOptionsMenu() 方法創(chuàng)建 App Bar 中的菜單項(xiàng)。
- 處理菜單項(xiàng)點(diǎn)擊事件:使用 onOptionsItemSelected() 方法處理 App Bar 中的菜單項(xiàng)點(diǎn)擊事件。
- 關(guān)聯(lián) App Bar 和布局:使用 setSupportActionBar() 方法將 App Bar 與布局關(guān)聯(lián)起來。
- 啟用/禁用 App Bar:使用 setEnabled() 方法啟用或禁用 App Bar。
二、Navigation 特點(diǎn)
Navigation 提供了 可視化的 頁面導(dǎo)航圖 , 與 iOS 開發(fā)中的 Xcode 環(huán)境中的 StoryBoard 類似 ; 在 布局文件 的 Design 模式下 , 可以看到 Fragment 之間的跳轉(zhuǎn)關(guān)系 ;
在 Xml 布局文件中 , 通過在 Fragment 標(biāo)簽中 , 添加 action 標(biāo)簽 , 設(shè)置該標(biāo)簽 app:destination 屬性 , 完成 Fragment 之間的導(dǎo)航 ;
如果要 為 Fragment 跳轉(zhuǎn)設(shè)置動畫 , 可以直接在 Navigation 圖形化界面中選中某個跳轉(zhuǎn) , 然后直接在 布局文件的 Design 圖形化界面中 , 設(shè)置跳轉(zhuǎn)的動畫 ;
通過 safe args 可以實(shí)現(xiàn) Fragment 頁面之間的參數(shù)安全傳遞 , 傳統(tǒng)方式是使用 Intent 進(jìn)行數(shù)據(jù)傳遞 ;
通過該 Design 模式下的 Navigation 管理 , 可以對 菜單 , 底部導(dǎo)航欄 , 抽屜菜單 的頁面及跳轉(zhuǎn)邏輯 , 進(jìn)行統(tǒng)一管理 ;
支持 DeepLink 深層鏈接 , 可以直接跳轉(zhuǎn)到指定的 Fragment 中 ;
三、Navigation 重要組件
Navigation 重要組件 :
- Navigation Graph 組件 : 是 Navigation 組件中的 Xml 文件 , 這是新加入的 Xml 文件類型 , 該文件定義在 res 資源目錄下的 navigation 目錄下 , 該文件中包含了 應(yīng)用程序 中的所有界面 , 以及界面之間的跳轉(zhuǎn)關(guān)系 ;
- NavHostFragment 組件 : 該組件是 Navigation 組件的核心組成部分 , 它可以看做為一個空的 Fragment 容器 , 用于在應(yīng)用中顯示目的地 , NavHostFragment 會自動處理目的地之間的轉(zhuǎn)換和回退操作 ; Navigation Graph 中定義的 Fragment 頁面 需要通過 NavHostFragment 進(jìn)行展示 ;
- NavController 組件 : 該組件是 NavHostFragment 中的管理對象 , 用于管理應(yīng)用中的導(dǎo)航操作 , 主要是完成在 Navigation Graph 中定義的頁面切換操作 ; 通過 NavController 可以輕松地跳轉(zhuǎn)到不同的目的地 , 并處理回退操作 ;
切換 Fragment 顯示流程 :
- 使用 NavController 組件 切換 Fragment , 設(shè)置 要跳轉(zhuǎn)的 定義在 Navigation Graph 中定義的 Fragment ;
- NavController 組件 會將 指定的 Fragment 顯示到 NavHostFragment 組件中 ;
四、Navigation 使用流程
Navigation 使用流程 :
- 創(chuàng)建若干 Fragment 頁面
- 創(chuàng)建 Navigation Graph , 并指定要跳轉(zhuǎn)的 destination 頁面
- 創(chuàng)建 NavHostFragment 組件
- 執(zhí)行 Fragment 頁面跳轉(zhuǎn) , 并添加動畫效果
- 使用 NavController 組件實(shí)現(xiàn)頁面導(dǎo)航
- 使用 Safe Args 插件安全傳遞數(shù)據(jù)
創(chuàng)建 Navigation Graph 組件有一個前提 , 那就是 Fragment 已經(jīng)創(chuàng)建完畢 ;
創(chuàng)建 NavHostFragment 組件有一個前提 , 那就是 Navigation Graph 已經(jīng)創(chuàng)建完畢 ;
1、創(chuàng)建 Fragment
右鍵點(diǎn)擊 代碼 包名 , 在彈出的右側(cè)菜單中 , 選擇 " New / Fragment / Fragment (Blank) " 選項(xiàng) ,
輸入 Fragment 名稱 " FragmentA " , 然后點(diǎn)擊 " Finish " 按鈕 , 創(chuàng)建完畢 ;
創(chuàng)建后的 Fragment 會自動生成一系列代碼 :
package kim.hsl.nav
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [FragmentA.newInstance] factory method to
* create an instance of this fragment.
*/
class FragmentA : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_a, container, false)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FragmentA.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
FragmentA().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
同時還會在 " res/layout " 目錄中 , 自動生成 FragmentA 對應(yīng)的布局文件 " fragment_a.xml " ,
自動生成的布局文件代碼如下 :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FragmentA">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
2、創(chuàng)建 Navigation Graph 組件
創(chuàng)建 Navigation Graph 組件有一個前提 , 那就是 Fragment 已經(jīng)創(chuàng)建完畢 ;
右鍵點(diǎn)擊 res 資源目錄 , 選擇 " New / Android Resource File " 選項(xiàng) ,
在彈出的對話框中 , 選擇 Resource Type 為 Navigation , 其 Directory name 會被自動設(shè)置為 navigation , 需要自定義設(shè)置的是 File name , 輸入文件名稱即可 , 這里命名為 navigation_graph.xml ;
生成的 " res/navigation/navigation_graph.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"
android:id="@+id/navigation_graph">
</navigation>
3、處理 Navigation Graph 組件報(bào)錯信息 " failed to add navigation dependency "
創(chuàng)建完成后 , 出現(xiàn)如下報(bào)錯信息 " failed to add navigation dependency " ;
點(diǎn)擊該界面 , 會彈出如下對話框 , 點(diǎn)擊 OK , 會自動向 build.gradle 構(gòu)建腳本中添加依賴 ;
被添加的依賴如下 :
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
添加完依賴后 , 重新 Build 一下應(yīng)用 , Navigation 功能正常使用 ;
4、編輯 Navigation Graph 組件 - 創(chuàng)建 action 跳轉(zhuǎn)
點(diǎn)擊 Navigation Graph 中 Design 模式下 的 " New Destination " 按鈕 ,
在彈出的下拉菜單中 , 可以選擇之前創(chuàng)建的兩個 Fragment , 分別是 FragmentA 和 FragmentB , 對應(yīng)的 xml 布局文件是 fragment_a.xml 和 fragment_b.xml ;
在上述下拉菜單中 , 點(diǎn)擊 fragment_a , 即可將該 FragmentA 設(shè)置到面板中 , 點(diǎn)擊 fragment_b 即可將 FragmentB 設(shè)置到面板中 ;
設(shè)置完畢后 , 將 鼠標(biāo)移動到 fragmentA 上 , 可以看到右側(cè)的 圓圈 ,
在 圓圈 上 , 按住鼠標(biāo)左鍵 , 拖動到 fragmentB 上 , 會自動生成一個箭頭 , 這個箭頭就是 action , 代表了一次跳轉(zhuǎn) ;
也可以設(shè)置一個從 fragmentB 到 fragmentA 的 action 箭頭 ;
5、創(chuàng)建 NavHostFragment 組件
創(chuàng)建 Navigation Graph 組件有一個前提 , 那就是 Fragment 已經(jīng)創(chuàng)建完畢 ;
創(chuàng)建 NavHostFragment 組件有一個前提 , 那就是 Navigation Graph 已經(jīng)創(chuàng)建完畢 ;
NavHostFragment 組件 需要設(shè)置在 Activity 中 , 具體是在 Activity 的布局文件中設(shè)置 NavHostFragment 容器組件 , 這是一個 UI 布局組件 ;
拖動 Container 下的 NavHostFragment 組件 到 Activity 布局中 ,
拖動后 , 需要選擇對應(yīng)的 Navigation Graph , 因此創(chuàng)建 NavHostFragment 組件有一個前提 , 那就是 Navigation Graph 已經(jīng)創(chuàng)建完畢 ;
然后設(shè)置該 NavHostFragment 組件 的約束布局選項(xiàng) , 充滿全屏 ;
生成的完整 Activity 布局文件代碼如下 :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
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/navigation_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
核心的 NavHostFragment 組件如下 :文章來源:http://www.zghlxwxcb.cn/news/detail-489670.html
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
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/navigation_graph" />
6、在 Activity 中獲取 NavController
通過 調(diào)用 findNavController 函數(shù) , 獲取 NavController , 然后通過該 NavController 變量進(jìn)行導(dǎo)航 ;文章來源地址http://www.zghlxwxcb.cn/news/detail-489670.html
// fragmentContainerView 組件的 管理 操作通過 NavController 完成
// 對應(yīng)的就是 navController 實(shí)例變量
val navController = findNavController(this, R.id.fragment)
NavigationUI.setupActionBarWithNavController(this, navController)
到了這里,關(guān)于【Jetpack】Navigation 導(dǎo)航組件 ① ( Navigation 引入 | Navigation 特點(diǎn) | Navigation 重要組件 | Navigation 使用流程 )的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!