• 《Jetpack Compose从入门到实战》第八章 Compose页面 导航


    请添加图片描述

    • 添加依赖:implementation “androidx.navigation:navigation-compose:$nav_version”

    Navigation for Compose

    class MainActivity : AppCompatActivity() {
    
        var theme: BloomTheme by mutableStateOf(BloomTheme.LIGHT)
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
    
                AppNavigation()
    
            }
        }
    }
    
    @Composable
    fun AppNavigation() {
        val navController = rememberNavController()
        NavHost(navController = navController, startDestination = "home") {
            composable("welcome") {
                WelcomeScreen(navController = navController)
            }
            composable("login") {
                LoginScreen(navController = navController)
            }
            composable("home") {
                HomeScreen(navController = navController)
            }
        }
    }
    
    fun WelcomeScreen(navController: NavController) {
        ...
        Button(onClick = { 
            navController.navigate("login") 
        
            navController.navigate("home"){
                popUpTo("welcome")
            }
    
            navController.navigate("home"){
                popUpTo("welcome"){ inclusive = true}
            }
    
            navController.navigate("home"){
                launchSingleTop = true
            }
        }) {
            Text(text = "Login in")
        }
    
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    导航时携带参数

    NavHost(...) {
            composable(
                "plantDetail/{plantId}/{fromBanner}",
                arguments = listOf(
                    navArgument("plantId"){type=NavType.IntType},
                    navArgument("fromBanner"){type=NavType.BoolType}
                )
            )
        }
    
    NavHost(...) {
            composable(
                "plantDetail/{plantId}?fromBanner={fromBanner}",
                arguments = listOf(
                    navArgument("fromBanner"){
                        type=NavType.BoolType
                        defaultValue = false
                    }
                )
            )
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 推荐用Id之类的索引参数传递,然后从本地或远程数据源请求
    • 尽量为导航参数添加默认值
    sealed class Screen(
        val route: String,
        @StringRes val resourceId: Int,
        val icon: ImageVector
    ){
        object Home:Screen("home",R.string.home, Icons.Filled.Home)
        object Favorite:Screen("home",R.string.favorite, Icons.Filled.Favorite)
        object Profie:Screen("home",R.string.profie, Icons.Filled.Profie)
        object Cart:Screen("home",R.string.cart, Icons.Filled.Cart)
    }
    
    val items = listOf(Screen.Home,Screen.Favorite,Screen.Profie,Screen.Cart)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    val navController = rememberNavController()
        Scaffold(
            bottomBar = {
                BottomNavigation{
                    val navBackStackEntry by navController.currentBackStackEntryAsState()
                    val currentDestination = navBackStackEntry?.destination
                    items.forEach { screen ->
                        BottomNavigationItem(
                            icon = { Icon(imageVector = screen.icon,
                                contentDescription = null) },
                            label = { Text(text = stringResource(screen.resourceId)) },
                            selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
                            selectedContentColor = Color.Red,
                            unselectedContentColor = Color.Gray,
                            onClick = {
                                navController.navigate(screen.route) {
                                    // Pop up to the start destination of the graph to
                                    // avoid building up a large stack of destinations
                                    // on the back stack as users select items
                                    popUpTo(navController.graph.findStartDestination().id) {
                                        saveState = false
                                    }
                                    // Avoid multiple copies of the same destination when
                                    // reselecting the same item
                                    launchSingleTop = true
                                    // Restore state when reselecting a previously selected item
                                    restoreState = false
                                }
                            }
                        )
                    }
                }
            }
        ) { innerPadding ->
            NavHost(navController, startDestination = Screen.Home.route, Modifier.padding(innerPadding)) {
                composable(Screen.Home.route) { HomeScreen(navController) }
                composable(Screen.Favorite.route) { FavoriteScreen(navController) }
                composable(Screen.Cart.route) { CartScreen(navController) }
                composable(Screen.Profile.route) { ProfileScreen(navController) }
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    嵌套导航图 Nested Navigation Graph

    • 一个App Module 由多个Lib Module组成
    • 添加lib依赖
    • 设置根NavHost和子NavHost

    导航DeepLinks

    • 跨模块跳转或者跨进程跳转,最好用这个

    依赖注入

    待补充

    sealed class Screen(
        val route: String,
        val title: String,
        val icon: ImageVector
    ) {
        object Home : Screen("home", "home", Icons.Filled.Home)
        object Favorite : Screen("favorite", "favorite", Icons.Filled.Favorite)
        object Notification : Screen("notification", "notification", Icons.Filled.Notifications)
        object Cart : Screen("cart", "cart", Icons.Filled.ShoppingCart)
    }
    
    val items = listOf(Screen.Home, Screen.Favorite, Screen.Notification, Screen.Cart)
    
    val uri = "android-app://compose.learn"
    
    @Preview
    @Composable
    fun Navigation2() {
        val navController = rememberNavController()
        Scaffold(bottomBar = {
            BottomNavigation {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentDestination = navBackStackEntry?.destination
                items.forEach { screen ->
                    BottomNavigationItem(selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
                        onClick = {
                            navController.navigate(screen.route) {
                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                launchSingleTop = true
                                restoreState = true
                            }
                        },
                        icon = {
                            Icon(screen.icon, contentDescription = "")
                        },
                        label = { Text(text = screen.title) })
                }
            }
        }) { innerPadding ->
            //deep link test:  adb shell am start -d "android-app://compose.learn/notification/adbTest" -a android.intent.action.VIEW
            NavHost(navController = navController, startDestination = Screen.Home.route, modifier = Modifier.padding(innerPadding)) {
                composable(Screen.Home.route) { navBackStackEntry ->
                    //viewModel()以composable为ViewModelStore,作用域只在当前的composable中
                    val exampleViewModel: ExampleViewModel = viewModel()
                    //多个destination之间共享viewmodel可以使用以下方法传入一个公共的ViewModelStoreOwner,这里是navBackStackEntry, 在多层路由下可以这样使用
                    val exampleViewModel2 = hiltViewModel<ExampleViewModel2>(navBackStackEntry)
                    Home()
                }
                composable(Screen.Favorite.route) { Favorite() }
                composable(
                    Screen.Notification.route,
                    deepLinks = listOf(navDeepLink { uriPattern = "$uri/notification/{from}" })
                ) { backStackEntry ->
                    Notification(backStackEntry.arguments?.getString("from"))
                }
                composable(Screen.Cart.route) { Cart() }
            }
        }
    }
    
    @Composable
    fun Home() {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            Text(text = "Home")
        }
    }
    
    @Composable
    fun Favorite() {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            Text(text = "Favorite")
        }
    }
    
    @Composable
    fun Notification(from: String?) {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            Text(text = "Notification from $from")
        }
    }
    
    @Composable
    fun Cart() {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            Text(text = "Cart")
        }
    }
    
    class ExampleViewModel : ViewModel() {
    
    }
    
    @HiltViewModel
    class ExampleViewModel2 @Inject constructor() : ViewModel() {
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    《Jetpack Compose从入门到实战》第一章 全新的 Android UI 框架

    《Jetpack Compose从入门到实战》 第二章 了解常用UI组件

    《Jetpack Compose从入门到实战》第三章 定制 UI 视图

    《Jetpack Compose从入门到实战》第八章 Compose页面 导航

    《Jetpack Compose从入门到实战》第九章 Accompanist 与第三方组件库

  • 相关阅读:
    GBase 8c V3.0.0数据类型——data_part
    G1垃圾回收器在并发场景调优
    16G DWDM SFP+光模块特性及解决方案
    分布式定时任务调度
    【AI绘画接口】Midjourney是什么?Midjourney有官方接口吗?
    Vue开发实战02-vue项目添加状态管理Vuex,路由router,以及http请求axios
    Spring Task Spring框架提供的任务调度工具
    软件测试之如何提升产品的用户体验度
    可视化容器管理工具-portainer.io使用
    C++中有哪些运算符以及它们的优先级?
  • 原文地址:https://blog.csdn.net/qq_61735602/article/details/133468904