目录
前言
Android Jetpack的Navigation确实好用,这里就简单记录一下,方便自己查阅。
这个出来了很久了,但也就偶尔用用,用完就忘了,正应了微信之父张小龙的名言[用完即走]。
PS: 好记性不如烂笔头。
正文
Jetpack的导航组件——Navigation,就可以很方便的管理各fragment之间的切换,让开发变得更简单。
Navigation主要由三部分组成:
- Navigation graph:一个包含所有导航相关信息的 XML 资源
- NavHostFragment:一种特殊的Fragment,用于承载导航内容的容器
- NavController:管理应用导航的对象,实现Fragment之间的跳转等操作
简单使用
一、添加依赖
dependencies {
def nav_version = "2.3.1"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
}
二、创建导航图
- 在“Project”窗口中,右键点击 res 目录,然后依次选择 New > Android Resource File。此时系统会显示 New Resource File 对话框。
- 在 File name 字段中输入名称,例如“nav_graph”。
- 从 Resource type 下拉列表中选择 Navigation,然后点击 OK。
三、创建Navigation graph
1. nav_graoh.xml
新建好的nav_graph.xml切换到design模式下,在 Navigation Editor 中,点击 New Destination 图标,然后点击 Create new destination,即可快速创建新的Fragment,
这里简单的创建FragmentA、FragmentB、FragmentC三个fragment来举例。
当然,如果要配置跳转关系,可以
通过手动配置页面之间的跳转关系,点击某个页面,右边会出现一个小圆点,拖曳小圆点指向跳转的页面,这里设置跳转的关系为FragmentA -> FragmentB -> FragmentC。
这种场景不是很多,现实中都是自己做指定跳转。
PS: 我这里不介绍这个,我用代码控制跳转关系。
因此,我的nav_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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/fragmentA">
<fragment
android:id="@+id/fragmentA"
android:name="com.biumall.view.fragment.FragmentA"
android:label="fragment_a"
tools:layout="@layout/fragment_a" />
<fragment
android:id="@+id/fragmentB"
android:name="com.biumall.view.fragment.FragmentB"
android:label="fragment_b"
tools:layout="@layout/fragment_b" />
<fragment
android:id="@+id/fragmentC"
android:name="com.biumall.view.fragment.FragmentC"
android:label="fragment_c"
tools:layout="@layout/fragment_c" />
</navigation>
代码简介:
- navigation是根标签。通过[app:startDestination="@id/fragmentA"]配置默认启动的第一个页面,这里配置的是FragmentA,改这个可以设置默认的Fragment。
- fragment标签代表一个fragment。有Fragment对应的配置信息。
2. activity_main.xml的代码配置
下面是activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<LinearLayout
android:id="@+id/main_left_layout"
android:layout_width="200dp"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/main_left_bt_a"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" A"
android:textSize="30sp" />
<Button
android:id="@+id/main_left_bt_b"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" B"
android:textSize="30sp" />
<Button
android:id="@+id/main_left_bt_c"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" C"
android:textSize="30sp" />
</LinearLayout>
<fragment
android:id="@+id/right_nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toEndOf="@+id/main_left_layout"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
tools:context=".MainActivity" />
</RelativeLayout>
PS: 我这里是要通Button进行切换Fragment的。
- android:name指定NavHostFragment
- app:navGraph指定导航视图,即建好的nav_graph.xml
- app:defaultNavHost=true 意思是可以拦截系统的返回键,可以理解为默认给fragment实现了返回键的功能,这样在fragment的跳转过程中,当我们按返回键时,就可以使得fragment跟activity一样可以回到上一个页面了。
PS:不使用Navigation,我们之前的Fragment没法直接获取到Back等事件的。
四、NavController的使用
我这里直接上代码
1. Activity中控制Fragment
private NavController mNavController = null;
mNavController = Navigation.findNavController(MainActivity.this, R.id.right_nav_host);
//这里切换FragmentA,如果要切换其他的,自行替换
mNavController.navigate(R.id.fragmentA);
2. Fragment中切换Fragment
这里有三种,分别如下:
方式一
fragmentABinding.aTvStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick: ");
//方式一
NavHostFragment.findNavController(FragmentA.this).navigate(R.id.fragmentB);
}
});
方式二
fragmentBBinding.bTvStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//方式二
Navigation.findNavController(getView()).navigate(R.id.fragmentC);
}
});
方式三
fragmentCBinding.cTvStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick : ");
//方三
Navigation.findNavController(getActivity(), R.id.right_nav_host).navigate(R.id.fragmentA);
}
});
PS: 上使用了Binding,各个Fragment的布局就不更新,就一个TextView。
参考文章
PS:参考文3有动图,写得很详细,大佬用心了。推荐先看这个,本文大部分内用都引用这篇文章,。
- 《Android Jetpack - 使用 Navigation 管理页面跳转》
- 《Android架构组件-Navigation的使用(一)》
- 《Android Navigation 组件(基础篇)》
- 《Android开发 navigation入门详解》