Jetpack Compose 导航 (Navigation)
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?.destinationBottomNavigation {items.forEach { screen ->BottomNavigationItem(selected = currentDestination?.route == screen.route,onClick = {navController.navigate(screen.route) {popUpTo(navController.graph.findStartDestination().id) {saveState = true}launchSingleTop = truerestoreState = 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的生命周期复杂性,使得导航逻辑更加直观和易于维护。