注意:Navigation 组件需要 Android Studio 3.3 或更高版本,并且依赖于 Java 8 语言功能。
如需在您的项目中添加 Navigation 支持,请向应用的 build.gradle 文件添加以下依赖项:
dependencies {
def nav_version = "2.4.2"
// 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"
// Feature module Support
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
// Testing Navigation
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
// Jetpack Compose Integration
implementation "androidx.navigation:navigation-compose:$nav_version"
}
创建导航图
当您添加首个导航图时,Android Studio 会在 res 目录内创建一个 navigation 资源目录。该目录包含您的导航图资源文件(例如 nav_graph.xml)。
添加图表后,Android Studio 会在 Navigation Editor 中打开该图表。在 Navigation Editor 中,您可以直观地修改导航图,或直接修改底层 XML。
向导航图中添加目的地
<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/my_nav"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.example.navigation.HomeFragment"
android:label="Home"
tools:layout="@layout/fragment_home">
</fragment>
</navigation>
Type 字段指示在您的源代码中,该目的地是作为 fragment、activity 还是其他自定义类实现的。
Label 字段包含该目的地的用户可读名称。例如,如果您使用 setupWithNavController() 将 NavGraph 连接到 Toolbar,就可能在界面上看到此字段。因此,我们建议您对此值使用资源字符串。
ID 字段包含该目的地的 ID,它用于在代码中引用该目的地。
将某个屏幕指定为起始目的地
起始目的地是用户打开您的应用时看到的第一个屏幕,也是用户退出您的应用时看到的最后一个屏幕。Navigation Editor 使用房子图标表示起始目的地。
所有目的地就绪后,您便可以选择起始目的地,具体操作步骤如下:
连接目的地
AS 上边有教程
完成之后,切换到 XML 视图。现在,一个 action 元素已添加到源目的地中。该操作有一个 ID 和一个目的地属性(其中包含下一个目的地的 ID),如以下示例所示:
<?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/my_nav"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.example.navigation.HomeFragment"
android:label="Home"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/action_homeFragment_to_detailFragment"
app:destination="@id/detailFragment" />
</fragment>
<fragment
android:id="@+id/detailFragment"
android:name="com.example.navigation.DetailFragment"
android:label="Detail"
tools:layout="@layout/fragment_detail">
<action
android:id="@+id/action_detailFragment_to_homeFragment"
app:destination="@id/homeFragment" />
</fragment>
</navigation>
导航宿主(NavHost) 是 Navigation 组件的核心部分之一。导航宿主是一个空容器,用户在您的应用中导航时,目的地会在该容器中交换进出。
通过 XML 添加 NavHostFragment
以下 XML 示例显示了作为应用主 Activity 一部分的 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=".navigationActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/my_nav" />
</androidx.constraintlayout.widget.ConstraintLayout>
请注意以下几点:
您也可以使用布局编辑器向 Activity 添加 NavHostFragment,具体操作步骤如下:
导航到目的地是使用 NavController 完成的,它是一个在 NavHost 中管理应用导航的对象。每个 NavHost 均有自己的相应 NavController。
在对应的 Fragment 中完成对应的跳转逻辑:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// 第一种写法
view.findViewById(R.id.homeButton).setOnClickListener(view1 -> {
NavController controller = Navigation.findNavController(view);
controller.navigate(R.id.action_homeFragment_to_detailFragment);
});
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// 第二种写法
view.findViewById(R.id.detail_button).setOnClickListener(
Navigation.createNavigateOnClickListener(R.id.action_detailFragment_to_homeFragment));
}
完成跳转逻辑之后就可以正常运行了。
右上角返回按钮的实现
在 Activity 中完成以下逻辑:
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
NavController controller = navHostFragment.getNavController();
NavigationUI.setupActionBarWithNavController(this, controller);
这部分只能将按钮显示出来。
为了实现返回功能,还要重写 onSupportNavigateUp() 方法:
@Override
public boolean onSupportNavigateUp() {
//return super.onSupportNavigateUp();
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
NavController controller = navHostFragment.getNavController();
return controller.navigateUp();
}
定义目的地参数:
如需在目的地之间传递数据,首先请按照以下步骤将参数添加到接收它的目的地来定义参数:
<fragment android:id="@+id/myFragment" >
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="0" />
</fragment>
使用 Bundle 对象在目的地之间传递参数:
// 传递
Bundle bundle = new Bundle();
bundle.putString("name", "ljh");
Navigation.findNavController(view1).navigate(R.id.action_homeFragment_to_detailFragment, bundle);
// 接收
String name = getArguments().getString("name");
Navigation 组件还包含几个默认动画,以帮助您快速入门。如需向操作添加动画,请执行以下操作:
1.在 Navigation Editor 中,点击应发生动画的操作。
2.在 Attributes 面板的 Animations 部分中,点击要添加的动画旁边的下拉箭头。您可以从以下类型中进行选择:
3.从显示的项目动画列表中选择动画。
添加动画后,点击 Text 标签页,以切换到 XML 文本视图。动画的 XML 现在显示在相应的 元素中。
<fragment
android:id="@+id/homeFragment"
android:name="com.example.navigation.HomeFragment"
android:label="Home"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/action_homeFragment_to_detailFragment"
app:destination="@id/detailFragment"
// 入场动画,针对目的地
app:enterAnim="@anim/slide_from_left"
// 退场动画,针对起始地
app:exitAnim="@anim/slide_to_right">
</action>
</fragment>
动画的使用请参考:动画使用