Navigation使用笔记--基本用法
Navigation是什么
jetpack组件,可视化管理Fragment切换
接入过程
gradle 配置
模块gradle配置
implementation "androidx.navigation:navigation-fragment-ktx:2.4.1"
implementation "androidx.navigation:navigation-ui-ktx:2.4.1"
plugins {
...
id "androidx.navigation.safeargs.kotlin"
}
项目gradle配置
buildscript {
...
dependencies {
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5"
}
}
activity的布局文件中
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_setting" />
</androidx.constraintlayout.widget.ConstraintLayout>
-
布局容器为androidx.fragment.app.FragmentContainerView
-
android:name="androidx.navigation.fragment.NavHostFragment" 为固定写法
-
app:navGraph="@navigation/nav_setting" 为指定跳转控制器
接下来看一下navigation如何配置的
res下新建navigation文件夹,在该文件夹下新建 选择 Navigation resource file
以下为一个标准示例
<?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/nav_test"
app:startDestination="@id/fragment1">
<fragment
android:id="@+id/fragment1"
android:name="com.relax.myapplication.navigationtest.Fragment1"
tools:layout="@layout/fragment_1"
android:label="fragment1">
<action
android:id="@+id/action_fragment1_to_fragment2"
app:destination="@id/fragment2"
app:enterAnim="@anim/base_slide_right_in"/>
</fragment>
<fragment
android:id="@+id/fragment2"
android:name="com.relax.myapplication.navigationtest.Fragment2"
tools:layout="@layout/fragment_2"
android:label="fragment2">
<action
android:id="@+id/action_fragment2_to_fragment3"
app:destination="@id/fragment3"
app:enterAnim="@anim/base_slide_right_in"/>
</fragment>
<fragment
android:id="@+id/fragment3"
android:name="com.relax.myapplication.navigationtest.Fragment3"
tools:layout="@layout/fragment_3"
android:label="fragment3"/>
</navigation>
根标签为navigation:
-
属性id用于被activity_layout中引用
-
属性startDestination为该activity中起始展示的页面
子标签 fragment 为fragment相关配置
-
属性id,当前navigation文件中fragment的id
-
属性name,fragment的路径地址
-
属性layout,fragment的布局文件
fragment的子标签action,为跳转相关配置
-
属性id,当前action的id,一般在代码中使用
-
属性destination,跳转目标fragment的id
-
属性enterAnim,fragment进入动画
-
属性exitAnim,fragment移除动画
在程序中使用
-
activity中使用
val navController = findNavController(R.id.nav_host_fragment) navController.navigate(R.id.action_fragment2_to_fragment3)
-
fragment中使用
getView()?.findViewById<TextView>(R.id.tv_to_f2)?.setOnClickListener { findNavController().navigate(R.id.action_fragment1_to_fragment2) }
可以看出相比FragmentManger 代码简洁易维护
跳转传参
跳转控制建议使用SafeArgs Gradle插件
优势 传参友好。使用get、set方式传惨,避免了key造成的耦合
fragment标签下的子标签配置
<?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/nav_test"
app:startDestination="@id/fragment1">
<fragment
android:id="@+id/fragment1"
android:name="com.relax.myapplication.navigationtest.Fragment1"
tools:layout="@layout/fragment_1"
android:label="fragment1">
<action
android:id="@+id/action_fragment1_to_fragment2"
app:destination="@id/fragment2" />
<argument
android:name="plantName"
app:argType="string" />
<argument
android:name="plantId"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/fragment2"
android:name="com.relax.myapplication.navigationtest.Fragment2"
tools:layout="@layout/fragment_2"
android:label="fragment2">
<action
android:id="@+id/action_fragment2_to_fragment3"
app:destination="@id/fragment3" />
</fragment>
</navigation>
设置参数
var bundle = Fragment1Args("name","id").toBundle()
findNavController().navigate(R.id.action_fragment1_to_fragment2,bundle)
获取参数
arguments?.let {
var id = Fragment2Args.fromBundle(it).plantId
}
Fragment2Args.fromBundle(requireArguments()).plantName
劣势
-
回退事件,在activity中可以通过startActivityForResult的方式回传参数,这里就比较复杂
-
底层实际调用replace方法,故无法保存状态
不出意外的话,下篇文章会介绍如何弥补以上两个劣势
参考资料
https://www.jianshu.com/p/5cd63ecabbf5
https://blog.csdn.net/weixin_42046829/article/details/110466717
https://www.cnblogs.com/guanxinjing/p/11555217.html