Navigation 官方文檔:
https://developer.android.google.cn/guide/navigation/navigation-getting-started?hl=zh-cn
Navigation 是用來管理 Fragment 的切換投储,并且可以通過可視化的方式浦辨,看見App的交互流程俘种。
優(yōu)點:
1探越、處理 Fragment 的切換(上文已說過)
2乔宿、默認情況下正確處理 Fragment 的前進和后退
3、為過渡和動畫提供標準化的資源
4饰抒、實現(xiàn)和處理深層連接
5阔加、可以綁定 Toolbar 奢啥、 BottomNavigationView 和 ActionBar 等
6、SafeArgs (Gradle插件) 數(shù)據(jù)傳遞時提供類型安全性
7嘴拢、ViewModel 支持
Navigation 組件由三個關鍵部分組成桩盲,這三個部分協(xié)同工作。它們是:
1席吴、導航圖(新 XML 資源)赌结,創(chuàng)建 navigation 文件夾,在 navigation 文件夾中新建xml導航圖
2孝冒、NavHostFragment柬姚,在 NavigationActivity 中加入 NavHostFragment(當前fragment的容器)
3、NavController庄涡,導航的控制者
【1】依賴
//Navigation
implementation "androidx.navigation:navigation-fragment-ktx:2.3.5"
implementation "androidx.navigation:navigation-ui-ktx:2.3.5"
【2】新建導航圖
1量承、在res目錄下新建navigation文件夾
2、在navigation文件夾新建xml文件 demo_nav.xml 文件穴店,如下圖:
image.png
<?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"
android:id="@+id/demo_nav"
app:startDestination="@id/oneFragment">
<fragment
android:id="@+id/oneFragment"
android:name="com.yunchong.jetpack.fragments.OneFragment"
android:label="fragment_one"
tools:layout="@layout/fragment_one" >
<action
android:id="@+id/action_oneFragment_to_twoFragment"
app:destination="@id/twoFragment" />
</fragment>
<fragment
android:id="@+id/twoFragment"
android:name="com.yunchong.jetpack.fragments.TwoFragment"
android:label="fragment_two"
tools:layout="@layout/fragment_two" >
<action
android:id="@+id/action_twoFragment_to_threeFragment"
app:destination="@id/threeFragment" />
</fragment>
<fragment
android:id="@+id/threeFragment"
android:name="com.yunchong.jetpack.fragments.ThreeFragment"
android:label="fragment_three"
tools:layout="@layout/fragment_three" />
</navigation>
他們的導航關系如下:
image.png
navigation:是導航標簽撕捍,管理多個fragment標簽
startDestination:指定第一個展示的fragment
action的destination:指定當前fragment的下一個跳轉目標
【3】fragment文件
fragment 文件可以是在導航地圖中新建:
image.png
也可以使用已有的fragment。
目前新建了3個fragment:
class OneFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_one, container, false)
view.back.setOnClickListener {
}
view.next.setOnClickListener {
}
return view
}
}
其他兩個文件和以上代碼差不多泣洞,F(xiàn)ragment的xml布局這里就不展示了忧风。
【4】在Activity中加載Navigation地圖
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/demo_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/demo_nav"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
其中最重要的三行代碼是:
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/demo_nav"
前面兩行代碼是固定格式,第三句代碼指定了Navigation地圖球凰。
【5】fragment 切換
Navigation優(yōu)化了 fragment 的事務處理狮腿,Navigation使fragment的切換變得簡單。
從一個fragment切換到下一個fragment:
Navigation.findNavController(view).navigate(R.id.action_oneFragment_to_twoFragment, bundle, navOption)
// 或者
// findNavController().navigate(R.id.action_oneFragment_to_twoFragment, bundle, navOption)
Navigation.findNavController(view) 和 findNavController() 是控制器呕诉,
action_oneFragment_to_twoFragment 是導航地圖中action中定義的id缘厢。
彈出fragment:
Navigation.findNavController(view).popBackStack()
// 或者
// findNavController().popBackStack()
popBackStack 可以指定 destinationId 參數(shù),如果沒有指定义钉,則默認彈出當前fragment 并切換到上一個fragment昧绣。
如果指定了 destinationId 參數(shù),那么將會一直彈出捶闸,直到 destinationId 為止夜畴。
【6】數(shù)據(jù)傳遞方式
【1】使用 ViewModelProvider 可以做到 Activity 和 fragment 之間數(shù)據(jù)共享
ViewModelProvider(this).get(T::class.java)
【2】Bundle 傳遞
fragment 之間可以使用 Bundle 傳遞方式:
view.next.setOnClickListener {
// 參數(shù)設置
val bundle = Bundle()
bundle.putString("name","zhangsan")
// 傳遞
Navigation.findNavController(view).navigate(R.id.action_oneFragment_to_twoFragment, bundle)
}
// 接收
val name: String? = arguments?.getString("name") // 獲取上級頁面?zhèn)鬟f過來的文本
【3】利用 Safe Args 插件傳遞參數(shù)
由于類型安全拖刃,使用 safe args 生成的類的導航是按操作導航以及在導航期間傳遞參數(shù)的首選方式。
第一步贪绘、添加 safe args 插件:
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.1'
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
}
}
第二步兑牡、在模塊下添加:
plugins {
id 'org.jetbrains.kotlin.android.extensions'
id 'androidx.navigation.safeargs.kotlin'
}
第三步、在Navigation地圖中添加argument
<fragment
android:id="@+id/twoFragment"
android:name="com.yunchong.jetpack.fragments.TwoFragment"
android:label="fragment_two"
tools:layout="@layout/fragment_two" >
<action
android:id="@+id/action_twoFragment_to_threeFragment"
app:destination="@id/threeFragment" />
<argument
android:name="name"
android:defaultValue="zhangsan"
app:argType="string"/>
</fragment>
第四步税灌、發(fā)送數(shù)據(jù)
val bundle = OneFragmentDirections.actionOneFragmentToTwoFragment(name = "hello zhangsan").arguments
Navigation.findNavController(view).navigate(R.id.action_oneFragment_to_twoFragment, bundle, null)
第五步均函、接收數(shù)據(jù)
val safeArgs: TwoFragmentArgs by navArgs()
val name = safeArgs.name
【7】fragment切換動畫
view.next.setOnClickListener {
// 設置動畫參數(shù)
val navOption = navOptions {
anim {
enter = R.anim.slide_in_right
exit = R.anim.slide_out_left
popEnter = R.anim.slide_in_left
popExit = R.anim.slide_out_right
}
}
Navigation.findNavController(view).navigate(R.id.action_oneFragment_to_twoFragment, null, navOption)
}
或者在action中定義:
<fragment
android:id="@+id/oneFragment"
android:name="com.yunchong.jetpack.fragments.OneFragment"
android:label="fragment_one"
tools:layout="@layout/fragment_one" >
<action
android:id="@+id/action_oneFragment_to_twoFragment"
app:destination="@id/twoFragment"
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>
slide_in_right 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="100%"
android:toXDelta="0%"
android:fromYDelta="0%"
android:toYDelta="0%"
android:duration="700"/>
</set>
slide_out_left 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0%"
android:toXDelta="-100%"
android:fromYDelta="0%"
android:toYDelta="0%"
android:duration="700"/>
</set>
slide_in_left 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="-100%"
android:toXDelta="0%"
android:fromYDelta="0%"
android:toYDelta="0%"
android:duration="700"/>
</set>
slide_out_right 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0%"
android:toXDelta="100%"
android:fromYDelta="0%"
android:toYDelta="0%"
android:duration="700"/>
</set>
【8】navigation可以和一些控件綁定
Navigation 可以綁定 menus 、 drawers 菱涤、 bottom navigation苞也、CollapsingToolbarLayout、Toolbar粘秆,它們提供
view.setupWithNavController(navController)
方法如迟,來綁定navigation控制器。
[本章完...]