Navigation的使用

Posted by alonealice on 2020-05-24

Google官方的描述:

今天,我们宣布推出Navigation组件,作为构建您的应用内界面的框架,重点是让单 Activity 应用成为首选架构。利用Navigation组件对 Fragment 的原生支持,您可以获得架构组件的所有好处(例如生命周期和 ViewModel),同时让此组件为您处理 FragmentTransaction 的复杂性。此外,Navigation组件还可以让您声明我们为您处理的转场。它可以自动构建正确的“向上”和“返回”行为,包含对深层链接的完整支持,并提供了帮助程序,用于将导航关联到合适的 UI 小部件,例如抽屉式导航栏和底部导航。

添加依赖

1
2
implementation "android.arch.navigation:navigation-fragment:1.0.0"
implementation "android.arch.navigation:navigation-ui:1.0.0"

添加fragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class NavigationFragment1 extends Fragment{

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_navigation,container,false);
((TextView)rootView.findViewById(R.id.tv_navi)).setText("NavigationFragment1");
rootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Navigation.findNavController(v).navigate(R.id.nav_page2);
}
});
return rootView;
}
}

class NavigationFragment2 extends Fragment{

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_navigation,container,false);
((TextView)rootView.findViewById(R.id.tv_navi)).setText("NavigationFragment2");
rootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Navigation.findNavController(v).navigate(R.id.nav_page3);
}
});
return rootView;
}
}

class NavigationFragment3 extends Fragment{

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_navigation,container,false);
((TextView)rootView.findViewById(R.id.tv_navi)).setText("NavigationFragment3");
rootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Navigation.findNavController(v).navigateUp();
}
});
return rootView;
}
}

新建导航文件

在res目录下新建navigation文件夹,然后新建一个navigation的resource文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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"
android:id="@+id/nav"
app:startDestination="@id/nav1">
<fragment android:id="@+id/nav1"
android:name="com.example.jetpackdemo.navigation.NavigationFragment1">
<action android:id="@+id/nav_page2"
app:destination="@id/nav2"></action>
</fragment>

<fragment android:id="@+id/nav2"
android:name="com.example.jetpackdemo.navigation.NavigationFragment2"
>
<action android:id="@+id/nav_page3"
app:destination="@id/nav3"></action>
<action android:id="@+id/nav_page1"
app:popUpTo="@id/nav1"></action>
</fragment>

<fragment android:id="@+id/nav3"
android:name="com.example.jetpackdemo.navigation.NavigationFragment3">
<action android:id="@+id/nav_page_1"
app:destination="@id/nav1"></action>
</fragment>

</navigation>

编辑MainActivity

在MainActivity的xml中添加NavHostFragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">

<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/nav"
/>

</FrameLayout>

这个相当于是导航界面的容器,里面添加了一个NavHostFragment。同时在activity中重写onSupportNavigateUp方法,将back键点击事件的委托出去

Navigation.findNavController(View) 返回了一个 NavController ,它是整个 Navigation 架构中 最重要的核心类,我们所有的导航行为都由 NavController 处理。里面有两个方法navigate和navigateUp,表示跳转到指定的fragment和上一个fragment。

NavGraphFragment内部实例化了一个FrameLayout, 作为ViewGroup的载体,导航并展示其它Fragment

在xml配置的app:defaultNavHost="true"这个属性意味着你的NavGraphFragment将会 拦截系统Back键的点击事件,同时 必须重写 Activity的 onSupportNavigateUp() 方法。

nav.xml以声明其导航的结构。

在跟节点中配置papp:startDestination="@id/nav1",表示nav1 的fragment会被默认加载到容器中。

在每个fragment‘中会声明action,其中的app:destination的属性,声明了这个行为导航的 destination(目的地),我们可以看到,它会指印跳转到 对应id 的Fragment。

同时Navigation还提供了一个 app:popUpTo 属性,它的作用是声明导航行为返回到 id对应的Fragment