导航组件由以下三个关键部分组成:
dependencies {
// Java language implementation
implementation "androidx.navigation:navigation-fragment:2.3.0"
implementation "androidx.navigation:navigation-ui:2.3.0"
}
可通过一下步骤创建导航图:
右键点击 res 目录,然后依次选择 New > Android Resource File。此时系统会显示 New Resource File 对话框
在 File name 字段中输入名称,例如“nav_graph”
从 Resource type 下拉列表中选择 Navigation,然后点击 OK
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph">
navigation>
添加导航图后,Android Studio 会在 Navigation Editor 中打开该图表。在 Navigation Editor 中,您可以直观地修改导航图,或直接修改nav_graph.xml
Navigation 组件旨在用于具有一个主 Activity 和多个 FragmentDestination 的应用
主 Activity 与导航图相关联,且包含一个负责根据需要交换Destination的 NavHostFragment
NavHost是 Navigation 组件的核心部分之一。NavHost是一个空容器,用户在您的应用中导航时,目的地会在该容器中交换进出
<LinearLayout 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:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
LinearLayout>
android:name 属性值为 NavHost 实现类的全类名
app:navGraph 属性将 NavHostFragment 与导航图相关联。导航图会在此 NavHostFragment 中指定用户可以导航到的所有Destination
app:defaultNavHost=“true” 属性确保 NavHostFragment 会拦截系统返回按钮.如果同一布局(例如,双窗格布局)中有多个NavHost,则必须并且只能指定一个默认的NavHost
从上图中可以看到,当在activity_main.xml中添加了NavHost后,Navigation Editor中已经列出了NavHost所在的布局文件
创建Fragment,例如IndexDestinationFragment
将Fragment作为一个Destination添加到nav_graph中
<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">
<fragment
android:id="@+id/index_fragment"
android:name="com.gale.navigation_01.fragments.IndexDestinationFragment"
android:label="Index"
tools:layout="@layout/fragment_index_destination"/>
navigation>
设置起始Destination:将navigation的startDestination属性的值指定为FragmentDestination的id即可
<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/index_fragment">
<fragment
android:id="@+id/index_fragment"
android:name="com.gale.navigation_01.fragments.IndexDestinationFragment"
android:label="Index"
tools:layout="@layout/fragment_index_destination"/>
navigation>
此时打开Navigation Editor后,如图所示,Graph Editor多了一个Destination,并且在其上方多了一个小房子,表示该Destination为起始Destination
创建Activity,例如DestinationActivity
将Activity作为一个Destination添加到nav_graph中
<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/index_fragment">
<fragment
android:id="@+id/index_fragment"
android:name="com.gale.navigation_01.fragments.IndexDestinationFragment"
android:label="IndexDestinationFragment"
tools:layout="@layout/fragment_index_destination"/>
<activity
android:id="@+id/destination_activity"
android:name="com.gale.navigation_01.DestinationActivity"
android:label="DestinationActivity"
tools:layout="@layout/activity_destination"/>
navigation>
此时打开Navigation Editor后,如图所示,Graph Editor多了一个ActivityDestination
在源Destination中添加action元素即可,action元素有一个id和一个destination属性(其值为下一个目的Destination的id)
<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/index_fragment">
<fragment
android:id="@+id/index_fragment"
android:name="com.gale.navigation_01.fragments.IndexDestinationFragment"
android:label="IndexDestinationFragment"
tools:layout="@layout/fragment_index_destination">
<action
android:id="@+id/to_destination_activity"
app:destination="@id/destination_activity"/>
fragment>
<activity
android:id="@+id/destination_activity"
android:name="com.gale.navigation_01.DestinationActivity"
android:label="DestinationActivity"
tools:layout="@layout/activity_destination"/>
navigation>
此时打开Navigation Editor后,如图所示,Graph Editor中的两个Destination已经建立了连接
导航到Destination是使用 NavController 完成的
在Activity中获取 NavController ,必须保证该Activity中有NavHost
获取NavController
//navHostView:要求其必须包含NavHost的实现类
View navHostView = findViewById(R.id.nav_host_fragment);
NavController navController = Navigation.findNavController(navHostView);
//或者
//R.id.nav_host_fragment:要求其指向的控件必须包含NavHost的实现类
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
通过NavController的navigate方法导航到Destination
//navigate方法的形参为nav_graph.xml中指定的action的id
navController.navigate(R.id.to_destination_activity);
在Fragment中获取 NavController
NavController navController = NavHostFragment.findNavController(this);
通过NavController的navigate方法导航到Destination
//navigate方法的形参为nav_graph.xml中指定的action的id
navController.navigate(R.id.to_destination_activity);
为要跳转的Destination添加DeepLink
<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/index_fragment">
<fragment
android:id="@+id/index_fragment"
android:name="com.gale.navigation_01.fragments.IndexDestinationFragment"
android:label="IndexDestinationFragment"
tools:layout="@layout/fragment_index_destination">
<action
android:id="@+id/to_destination_activity"
app:destination="@id/destination_activity" />
fragment>
<activity
android:id="@+id/destination_activity"
android:name="com.gale.navigation_01.DestinationActivity"
android:label="DestinationActivity"
tools:layout="@layout/activity_destination">
<deepLink
app:uri="http://activity/destination_activity" />
activity>
navigation>
通过Destination指定的DeepLink的uri进行跳转
navController.navigate(Uri.parse("http://activity/destination_activity"));