Jetpack Navigation 组件简化了 Android 应用内的导航逻辑,统一管理 Fragment、Activity 的切换和回退栈。本文会从其核心功能、使用示例、适用场景、注意事项及版本兼容性等方面进行讲解。
一、核心概念与组件
1. 导航图(NavGraph)
XML 文件定义所有页面(目的地)及导航关系,支持参数传递和动画。
2. NavController
控制导航操作(如跳转、回退),管理回退栈。
3. NavHost
容器(如 NavHostFragment),用于显示导航图中的目的地(通常是 Fragment)。
4. Safe Args
类型安全的参数传递插件,生成导航操作的代码类。
二、使用示例
新建Activity -> Bottom Navigation Views Activity 即可.
1. 基础配置
-
添加依赖:
// build.gradle (app) dependencies { implementation "androidx.navigation:navigation-fragment-ktx:2.7.7" implementation "androidx.navigation:navigation-ui-ktx:2.7.7" // Safe Args 插件 classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7" } -
启用 Safe Args(在
app/build.gradle):plugins { id 'androidx.navigation.safeargs.kotlin' }
2. 创建导航图(nav_graph.xml)
<!-- res/navigation/nav_graph.xml -->
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.example.HomeFragment"
android:label="Home">
<action
android:id="@+id/action_to_detail"
app:destination="@id/detailFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left" />
</fragment>
<fragment
android:id="@+id/detailFragment"
android:name="com.example.DetailFragment"
android:label="Detail">
<argument
android:name="itemId"
app:argType="integer"
android:defaultValue="-1" />
</fragment>
</navigation>
3. 在 Activity 中设置 NavHost
<!-- activity_main.xml -->
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
4. 执行导航操作
-
从 HomeFragment 跳转到 DetailFragment:
// 使用 Safe Args 传递参数 val action = HomeFragmentDirections.actionToDetail(itemId = 123) findNavController().navigate(action) -
接收参数(DetailFragment 中):
private val args: DetailFragmentArgs by navArgs() val itemId = args.itemId
5. 底部导航栏集成
// MainActivity.kt
val navController = findNavController(R.id.nav_host)
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNav.setupWithNavController(navController)
6. 细节处理
// 去除BottomNavigationView item长按吐司问题
(binding.navView.getChildAt(0) as ViewGroup).children.forEach {
it.setOnLongClickListener { true }
}
//设置icon大小
binding.navView.itemIconSize =
resources.getDimensionPixelSize(R.dimen.home_icon_size)
// 取消BottomNavigationView item图标着色
binding.navView.itemIconTintList = null
// 设置字体颜色
val colors = intArrayOf(
resources.getColor(R.color.color_999999, theme),
resources.getColor(R.color.theme_red, theme)
)
binding.navView.itemTextColor = ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_checked),
intArrayOf(android.R.attr.state_checked)
),
colors
)
三、适用场景
1. 单 Activity 多 Fragment 架构
适用于主界面为底部导航栏或抽屉菜单的应用。
2. 条件性导航
根据用户登录状态跳转不同页面。
3. 深层链接(DeepLink)
从通知或网页直接打开应用内特定页面。
<deepLink app:uri="example://detail/{itemId}" />
4. 动态导航
根据业务逻辑动态修改导航图。
四、注意事项
1. 回退栈管理
- 使用
popUpTo和popUpToInclusive控制回退栈。
<action
android:id="@+id/action_to_login"
app:destination="@id/loginFragment"
app:popUpTo="@id/homeFragment"
app:popUpToInclusive="true" />
2. ViewModel 作用域
- 使用
by activityViewModels()共享 Activity 级数据。
3. 避免内存泄漏
- 在 Fragment 的
onDestroyView()中取消数据监听。
4. 动画冲突
- 确保导航动画与 Fragment 内部动画不冲突。
5. Safe Args 限制
- 复杂对象需实现
Parcelable或Serializable。
五、版本兼容性
| Navigation 版本 | 最低 Android API | 主要特性 |
|---|---|---|
| 2.3.x | API 14 (Android 4.0) | 支持 Fragment、Activity、深层链接、动态导航图。 |
| 2.4.0+ | API 21 (Android 5.0) | 支持多返回栈、改进动画兼容性。 |
| 2.7.x | API 21 (Android 5.0) | 增强与 Compose 集成、优化回退栈处理。 |
- AndroidX 要求:Navigation 必须与 AndroidX 库配合使用,不支持旧版 Support 库。
- Java 8+ :从 2.4.0 开始需启用 Java 8。
六、常见问题解决
1. 找不到目的地 ID
- 确保
nav_graph.xml中的 ID 与代码中一致。
2. 导航重复跳转
- 使用
navController.currentDestination?.id检查当前页面。
3. 深层链接不生效
- 在
AndroidManifest.xml中声明nav-graph:
<activity android:name=".MainActivity">
<nav-graph android:value="@navigation/nav_graph" />
</activity>
七、总结
- 优势:统一导航逻辑、简化代码、支持复杂跳转和 Safe Args。
- 推荐场景:单 Activity 应用、底部导航、需要动态导航逻辑。
- 最佳实践:结合 ViewModel 管理状态、使用 Safe Args 传递参数、合理设计导航图层级。
通过合理使用 Navigation 组件,可显著提升应用导航的可维护性和用户体验。