10.Navigation

Navigation概述

1
2
Navigation是指支持用户导航、进入和退出应用中不同内容片段的交互。用于处理Fragment事务,使fragment之间可以自由切换和跳转,
同时还包括导航界面模式(例如抽屉式导航栏和底部导航),可以降低用户工作量;

Navigation组成(核心三件套)

1
2
3
4
5
1.导航图:在一个集中位置包含所有导航相关信息的 XML 资源。包含用户可以跳转的所有路径,对Navigation来说就像是地图。
2.NavHost:用来显示导航图中目标所要展示的内容。
3.NavController:在 NavHost 中管理应用导航的对象。负责NavHost里内容的改变
如果要在应用中导航,则通过NavController,沿导航图中的特定路径导航至特定目标,或直接导航至特定目标。NavController 就可以
在NavHost里进行跳转。
1
2
3
4
5
6
7
8
9
10
11
 // 指定Navigation的版本
def nav_version = "2.5.3"

// Java language implementation
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"

// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

导航图使用方法

1.创建导航图

导航图是一种资源文件,其中包含Navigation所有目的地和操作。会显示应用的所有导航路径。

1.1. 具体操作

1
2
3
4
1.在“Project”窗口中,点击 res 目录,然后依次选择 New > Android Resource File。此时系统会显示 New Resource File 对话框。
2.在 File name 字段中输入Navigation的名称,例如“graph”。
3.从 Resource type 下拉列表中选择 Navigation,然后点击 OK。
这样就完成了空白导航图的创建,这时来到res文档下就会看到navigation文件夹还有你创建的导航图

res

2.向Activity添加NavHost

分成两种方法:

1
2
1. 通过 XML 添加
2. 使用布局编辑器添加(暂不介绍)

2.1. 通过 XML 添加

在activity中加入如下代码

1
2
3
4
5
6
7
8
9
10
<!-- 这里navGraph的值要改为自己导航图的名字 -->
<!-- app.defaultNavHost="true"表示回退栈由fragment管理 -->
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="409dp"
android:layout_height="729dp"
app:defaultNavHost="true"
app:navGraph="@navigation/navigation_map"
/>

3.在导航图中创建目的地

目的地相当于是导航图中的一个个地点,展示各种界面内容

3.1. 具体操作

1.双击导航图,点击右上角的Design,来到下图的 Navigation Editor 界面,点击图中标红图标,然后点击 Create new destination。

4

2.在接下来的对话框中,创建 Fragment,Android Studio会按照如下配置创建BlankFragment类和fragment_layout布局(fragment_layout中默认采用FrameLayout的布局,可以改成ConstraintLayout)

5

回到 Navigation Editor 界面就可以看到导航图中已经有了一个目的地

image-20231117101542044

3.连接目的地

操作会将一个目的地连接到另一个目的地,即一个界面是否可以跳转到另一个界面

为了演示,我在上面的基础上再建了一个BFragment

3.1. 具体操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1.在系统生成的AFragment类里的onCreateView方法里进行改动
2.通过 Navigation.findNavController(view) 方法得到对应 NavController
3.使用 NavController 里的 navigate(int) 方法进行导航,该方法的参数为两目的地之间连接的id或者要导向的目的地id

public class AFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_a, container, false);
inflate.findViewById(R.id.tv_text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// action_AFragment_to_BFragment为两目的地之间连接的id或者要导航向的目的地id,这个id在navigation_map
//的右上角自动生成的
Navigation.findNavController(v).navigate(R.id.action_AFragment_to_BFragment);
}
});
return inflate;
}
}

3.2Navigation的返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Navigation支持多个返回堆栈可让用户在各个页面之间自由切换,同时不会在任何页面中丢失所处的位置,不需要导航图中有对应的连接就可
以进行返回操作

具体操作:
1.在系统生成的BlankFragment类里的onCreateView方法里进行改动
2.通过 Navigation.findNavController(view) 方法得到对应 NavController
3.使用 NavController 里的 popBackStack() 方法即可完成返回

public class BFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_b, container, false);
inflate.findViewById(R.id.tvback).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//返回
Navigation.findNavController(v).popBackStack();
}
});
return inflate;
}
}

4.在目的地间传递数据(不研究导航地图的传参了,麻烦无用)

1
2
3
Bundle bundle=new Bundle();
bundle.putString("name", "tyl");
Navigation.findNavController(v).navigate(R.id.action_AFragment_to_BFragment,bundle);

接收方通过 getArguments() 方法得到 Bundle 对象并可以使用里面的内容

1
String name = getArguments().getString("name");

//BottomNavigationView看了下可扩展性差,不适合正式项目使用,直接不采用这个框架