简介
该组件可以实现用户界面跳转、转场动画以及安全的参数传递等功能。无论是简单的按钮点击,还是应用栏和抽屉式导航栏等更为复杂的模式,该组件均可应对。还可以使用 Android Studio 的 Navigation Editor 来查看和编辑导航图,使页面跳转流程更加直观。
Navigation 组件旨在用于具有一个主 Activity 和多个 Fragment 目的地的应用
依赖
在app的build.gradle文件中添加依赖:
dependencies {
......
def nav_version = "2.3.0"
// Navigation依赖(Java版)
//implementation "androidx.navigation:navigation-fragment:$nav_version"
//implementation "androidx.navigation:navigation-ui:$nav_version"
// Navigation依赖(Kotlin版)
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
// 动态功能模块支持
//implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
// 测试模块
//androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
}
如果要使用Safe Args的话,还需要添加插件依赖,
在项目的build.gradle文件中添加依赖:
dependencies {
......
def nav_version = "2.3.0-alpha01"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
在app的build.gradle文件最上面添加依赖:
//适用于 Kotlin 独有的模块的 Kotlin 代码
apply plugin: "androidx.navigation.safeargs.kotlin"
//或
//适用于 Java 或 Java 和 Kotlin 混合模块的 Java 语言代码
//apply plugin: "androidx.navigation.safeargs"
使用步骤
1、创建导航图
2、添加导航宿主NavHost
3、添加目的地
4、连接目的地
创建导航图
右键点击res目录–>选择New–>选择Android Resource File
在资源目录下,生成一个navigation导航文件夹和一个app_graph.xml导航图文件
添加fragment,通过设置属性,将主布局与导航图关联
<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">
<fragment
android:id="@+id/fm_nva_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/app_graph" />
androidx.constraintlayout.widget.ConstraintLayout>
android:name 固定值(也可以自己实现NavHostFragment),NavHost 实现的类名称
app:navGraph 设置导航图文件,将 NavHostFragment 与导航图相关联
app:defaultNavHost="true" 拦截系统返回按钮,多级Fragment界面,逐级返回
添加目的地
如果没有提前创建fragment界面,需要创建一个新的frament(目的地),
如果创建过,则可以直接选择已经创建的fragment界面
连接目的地会生成如下代码:
<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/nva_graph"
app:startDestination="@id/blankFragment"
tools:ignore="UnusedNavigation">
<fragment
android:id="@+id/blankFragment"
android:name="com.zzs.jetpack_navigation.BlankFragment"
android:label="fragment_blank"
tools:layout="@layout/fragment_blank" >
//action相当于连接线
<action
android:id="@+id/action_blankFragment_to_blankFragment2"
app:destination="@id/blankFragment2" />
fragment>
<fragment
android:id="@+id/blankFragment2"
android:name="com.zzs.jetpack_navigation.BlankFragment2"
android:label="fragment_blank_fragment2"
tools:layout="@layout/fragment_blank2" >
fragment>
navigation>
界面跳转
界面跳转有有多种方式,下面介绍两种:
1、action跳转(本质上也是id跳转),需实现Safe Args插件依赖
tv_jump.setOnClickListener {
val action = BlankFragmentDirections.actionBlankFragmentToBlankFragment2()
it.findNavController().navigate(action)
}
actionBlankFragmentToBlankFragment2实际上就是连接目的地后生成的action中的id的驼峰式命名
actionBlankFragmentToBlankFragment2()方法的源码:
class BlankFragmentDirections private constructor() {
companion object {
fun actionBlankFragmentToBlankFragment2(): NavDirections =
ActionOnlyNavDirections(R.id.action_blankFragment_to_blankFragment2)
}
}
2、id跳转
action_blankFragment_to_blankFragment2就是连接目的地后生成的action中的id
tv_jump.setOnClickListener {
it.findNavController().navigate(R.id.action_blankFragment_to_blankFragment2)
}
界面返回
按下返回键可直接返回上一级界面,不需要处理
如果需要主动返回上一级界面,可通过如下方式:
tv_back.setOnClickListener {
it.findNavController().navigateUp()
//或者
//it.findNavController().popBackStack()
}
navigateUp和popBackStack都可以返回上一级
区别:
navigateUp 如果当前的返回栈是空会停留在当前页面
popBackStack 如果当前的返回栈是空会报错
转场动画
设置转场动画有两种方式:
1、手动代码设置
在导航图文件中,添加如下代码:
<fragment
android:id="@+id/blankFragment"
android:name="com.zzs.jetpack_navigation.BlankFragment"
android:label="fragment_blank"
tools:layout="@layout/fragment_blank" >
<action
android:id="@+id/action_blankFragment_to_blankFragment2"
app:destination="@id/blankFragment2"
app:enterAnim="@anim/anim_in_enter"
app:exitAnim="@anim/anim_in_exit"
app:popEnterAnim="@anim/anim_out_enter"
app:popExitAnim="@anim/anim_out_exit" />
fragment>
enterAnim 和 exitAnim 是往栈里添加一个 目的地 时两个 目的地 的动画
popEnterAnim 和 popExitAnim 是从栈里移除一个 目的地 时的动画
转场动画文件
在资源文件中,新建anim文件夹,添加如下文件:
anim_in_enter.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="100%p"
android:toXDelta="0%p" />
set>
anim_in_exit.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="0%p"
android:toXDelta="-100%p" />
set>
anim_out_enter.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="-100%p"
android:toXDelta="0%p" />
set>
anim_out_exit.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="0%p"
android:toXDelta="100%p" />
set>
传递参数
传递参数有两种方式:
1、Safe Args传值,需实现Safe Args插件依赖
在导航图文件中设置传递的参数,两种方式
①手动添加代码
<fragment
android:id="@+id/blankFragment"
android:name="com.zzs.jetpack_navigation.BlankFragment"
android:label="fragment_blank"
tools:layout="@layout/fragment_blank" >
<action
android:id="@+id/action_blankFragment_to_blankFragment2"
app:destination="@id/blankFragment2"/>
<argument
android:name="name"
app:argType="string"
android:defaultValue="张三" />
<argument
android:name="sex"
app:argType="string"
android:defaultValue="男" />
<argument
android:name="age"
app:argType="integer"
android:defaultValue="20" />
fragment>
②在Design设计图中通过属性添加
在目的地BlankFragment2中接收参数
val args: BlankFragmentArgs by navArgs()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getArgs()
}
private fun getArgs() {
val name = args.name
val sex = args.sex
val age = args.age
tv_agrs.text =
"${resources.getString(R.string.send_args)}\nname=${name}\nsex=$sex\nage=$age"
}
如果navArgs()报红,需要在在app的build.gradle文件中添加如下代码:
android {
......
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
注意:我用Safe Args传值,接收到的中文参数都显示为乱码,目前没有找到解决办法
2、Bundle传值
在传值目的地BlankFragment中,代码如下:
tv_jump.setOnClickListener {
val bundle = bundleOf(
"name" to "张三",
"sex" to "男",
"age" to 20
)
it.findNavController().navigate(R.id.action_blankFragment_to_blankFragment2, bundle)
}
在接收目的地BlankFragment2中,代码如下:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getArgs()
}
private fun getArgs() {
val name = arguments?.getString("name")
val sex = arguments?.getString("sex")
val age = arguments?.getInt("age")
tv_agrs.text =
"${resources.getString(R.string.send_args)}\nname=${name}\nsex=$sex\nage=$age"
}
项目地址:https://github.com/zhangzs1994/Jetpack_Navigation