nagivation简化了android中的导航的实现,旨在用于具有一个主 Activity 和多个 Fragment 目的地的应用,可以让导航实现起来更加方便。
导航由三个关键部分组成
1.导航图:在一个集中位置包含所有导航相关信息的 XML 资源。这包括应用内所有单个内容区域(称为目标)以及用户可以通过应用获取的可能路径。
2.NavHost:显示导航图中目标的空白容器。导航组件包含一个默认 NavHost 实现 (NavHostFragment),可显示 Fragment 目标。
3.NavController:在 NavHost 中管理应用导航的对象。当用户在整个应用中移动时,NavController 会安排 NavHost 中目标内容的交换。
在应用中导航时,您告诉 NavController,您想沿导航图中的特定路径导航至特定目标,或直接导航至特定目标。NavController 便会在 NavHost 中显示相应目标。
使用
在应用的 build.gradle 文件添加以下依赖项:
dependencies {
def nav_version = "2.3.0-alpha01"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
}
导航图创建
导航图是一种资源文件,其中包含您的所有目的地和操作,目的地由操作连接,操作表示如何从一个目的地到另一个目的地。
- 右键点击 res 目录,然后依次选择 New > Android Resource File。弹出New Resource File 对话框。
- File name填入名称。
-
Resource type 中选择 Navigation。
创建导航图.png当添加首个导航图时,Android Studio 会在 res 目录内创建一个 navigation 资源目录。该目录包含您的导航图资源文件(例如 nav_graph.xml)
向 Activity 添加 NavHost
导航宿主是一个空容器,在其中切换不同的目的地,其必须派生于NavHost。Navigation中一个默认的实现是NavHostFragment
在主activity的xml文件里添加NavHostFragment
<?xml version="1.0" encoding="utf-8"?>
<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/nav_host_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="androidx.navigation.fragment.NavHostFragment"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
- android:name 属性包含 NavHost 实现的类名称。
- app:navGraph 属性将 NavHostFragment 与导航图相关联。导航图会在此 NavHostFragment 中指定用户可以导航到的所有目的地。
- app:defaultNavHost="true" 属性确保您的 NavHostFragment 会拦截系统返回按钮。请注意,只能有
。如果同一布局(例如,双窗格布局)中有多个主机,请务必仅指定一个默认 NavHost。
向导航图添加目的地
创建新的目的地
-
打开nav_graph.xml,进入design页面;点击左上角New Destination图标创建new destination.png
在随即显示的 New Android Component 对话框中,创建Fragment
默认第一个创建的destination为启动页, 我们也可选中destination单击右键来设置。
- 也可以选择创建占位符目的地,稍后可以用fragment获activity。即点击上图的placeholder,在xml文件生成只包含id属性的fragment标签,不生成fragment。
- 必须先将占位符的类属性更改为现有目的地,然后再运行应用。占位符不会导致编译错误,但如果尝试导航到占位符目的地,则应用会抛出运行时异常
也可以在<navigation>中用属性设置
app:startDestination="@id/blankFragment"
连接目的地
操作将一个目的地连接到另一个目的地。借助操作,可以表示用户在应用中导航时可以采取的不同路径。要实际导航到各个目的地,仍然需要编写代码来执行导航操作。
在 Design 标签页中,点击从中导航出来的目的地的右侧圆圈;将其拖到想要导航到的目的地上在XML 视图中,一个 action 元素已添加到源目的地中。
导航到目的地
导航的实际操作是由NavController完成,它是一个在 NavHost 中管理应用导航的对象,每个 NavHost 均有自己的相应 NavController。
可以用下面三种方式获得NavController:
- NavHostFragment.findNavController(Fragment)
- Navigation.findNavController(Activity, @IdRes int viewId)
- Navigation.findNavController(View)
获得之后调用navigate()方法导航到某个目的地
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//id为之前连接那步生成的action的id
controller.navigate(R.id.action_blankFragment2_to_blankFragment3);
}
});
导航和返回堆栈
Android 会维护一个返回堆栈,其中包含之前访问过的目的地,每次调用 navigate()都会将另一目的地放置到堆栈的顶部。
在关联的<action>元素中添加 app:popUpTo 属性可以将除目标目的地外的其他目的地都出栈。
设置app:popUpToInclusive="true",以表明在 app:popUpTo 中指定的目的地也应从返回堆栈中移除。
循环跳转的例子
A->B->C->A
在C->A的时候设置 app:popUpTo="@+id/a" 将栈中除A之外的目的地全部出栈;设置app:popUpToInclusive="true",将栈中A的实例也出栈,若不设置则栈中将有两个A实例。
<fragment
android:id="@+id/c"
android:name="com.example.myapplication.C"
android:label="fragment_c"
tools:layout="@layout/fragment_c">
<action
android:id="@+id/action_c_to_a"
app:destination="@id/a"
app:popUpTo="@+id/a"
app:popUpToInclusive="true"/>
</fragment>
在目的地之间传递数据
只建议传递少量数据,如果是大量数据的话可以使用ViewModel
首先要将参数添加到接收它的目的地来定义参数成功后在对应目的地的标签下生成了<argument/>标签
使用Bundle来传递参数
BlankFragment2传递数据
Bundle bundle = new Bundle();
bundle.putString("name", "炫神");
controller.navigate(R.id.action_blankFragment2_to_blankFragment3,bundle);
BlankFragment接受数据
tv = view.findViewById(R.id.textView);
tv.setText(getArguments().getString("name"));
为目的地创建深层链接
深层链接是指将用户直接转到应用内特定目的地的链接,有两种方式:显式深层链接和隐式深层链接。
显示深层链接
使用 PendingIntent将用户转到应用内的特定位置。可以在通知、应用快捷方式或应用微件中显示显式深层链接。
当通过显式深层链接打开应用时,任务返回堆栈会被清除,并被替换为相应的深层链接目的地。
还可以通过 NavController.createDeepLink()创建深层链接。
隐式深层链接
调用URI创建,在使用隐式深层链接时返回堆栈的状态取决于是否使用 Intent.FLAG_ACTIVITY_NEW_TASK 标记启动隐式 Intent
- 如果该标记已设置,则任务返回堆栈会被清除,并被替换为相应的深层链接目的地。当用户从深层链接目的地按下返回按钮时,会返回到相应的导航堆栈,就像从入口点进入应用。
- 如果该标记未设置,仍然位于上一个应用的任务堆栈中。在这种情况下,如果按下返回按钮,会返回到上一个应用(页面);如果按下向上按钮,则会导航图中的层次父级目的地上启动应用的任务。
要启用隐式深层链接,必须向应用的 manifest.xml 文件中添加内容。将一个 <nav-graph> 元素添加到指向现有导航图的 Activity
<activity name=".MainActivity" ...>
...
<nav-graph android:value="@navigation/nav_graph" />
...
</activity>