Jetpack Compose 提供了现代化的导航解决方案,与传统的 Fragment 导航不同,它完全基于 Composable 函数构建。以下是 Compose 导航的核心用法:
1. 基本设置
首先添加依赖:
implementation "androidx.navigation:navigation-compose:2.7.7" // 使用最新版本
2. 创建 NavController
val navController = rememberNavController()
// 在 Scaffold 或根布局中使用
ComposeAppTheme {
NavHost(navController = navController, startDestination = "home") {
// 定义各个屏幕
}
}
3. 定义导航图 (NavGraph)
NavHost(
navController = navController,
startDestination = "main_screen"
) {
composable("main_screen") { MainScreen(navController) }
composable("detail_screen/{itemId}") { backStackEntry ->
val itemId = backStackEntry.arguments?.getString("itemId")
DetailScreen(itemId, navController)
}
dialog("settings_dialog") { SettingsDialog(navController) }
}
4. 导航操作
跳转到新页面
// 基本导航
navController.navigate("detail_screen")
// 带参数导航
navController.navigate("detail_screen/123")
// 带对象参数 (需要自定义 NavType)
navController.currentBackStackEntry?.arguments?.apply {
putParcelable("key", myObject)
}
navController.navigate("detail_screen")
返回操作
// 简单返回
navController.popBackStack()
// 返回并传递结果
navController.previousBackStackEntry?.savedStateHandle?.set(
"result_key",
resultData
)
navController.popBackStack()
// 返回根页面
navController.popBackStack(
route = "main_screen",
inclusive = false
)
5. 高级功能
深层链接
composable(
"detail_screen/{id}",
deepLinks = listOf(
navDeepLink {
uriPattern = "example.com/detail/{id}"
}
)
)
底部导航栏集成
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
BottomNavigation {
items.forEach { screen ->
BottomNavigationItem(
selected = currentDestination?.route == screen.route,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
动画过渡
composable(
"screen1",
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Left) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Left) }
)
6. 最佳实践
-
1、使用密封类管理路由:
-
sealed class Screen(val route: String) { object Home : Screen("home") object Detail : Screen("detail/{id}") { fun createRoute(id: String) = "detail/$id" } }
-
2、避免直接传递复杂对象,使用ID然后在目标屏幕获取数据
-
3、处理返回按钮:
BackHandler(enabled = true) {
if (!navController.popBackStack()) {
// 处理无法返回的情况
}
}
-
ViewModel共享:使用
hiltViewModel()
在导航目标间共享ViewModel
Compose导航相比传统导航更简洁,所有界面都是Composable函数,没有Fragment的生命周期复杂性,使得导航逻辑更加直观和易于维护。