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

news2025/7/16 17:27:48

请添加图片描述

  • 添加依赖: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")
    }

    ...
}

导航时携带参数

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
                }
            )
        )
    }
  • 推荐用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)
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) }
        }
}

嵌套导航图 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() {

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1054774.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3核心源码解析 (一) : 源码目录结构

通过软件框架阅读源码可以对框架本身运行机制进行学习&#xff0c;更能了解框架的API设计、原理及流程、设计思路&#xff1b;我们要知其然&#xff0c;更知其所以然。 Vue 3的源码相对于Vue 2版本有了较大程度的改变&#xff0c;采用Monorepo规范的目录结构&#xff0c;同时使…

JavaScript——APIs

复习&#xff1a; splice() 方法用于添加或删除数组中的元素。 **注意&#xff1a;**这种方法会改变原始数组。 删除数组&#xff1a; splice(起始位置&#xff0c; 删除的个数) 比如&#xff1a;1 let arr [red, green, blue] arr.splice(1,1) // 删除green元素 consol…

【ArcGIS Pro二次开发】(69):使用MapTool实现隐藏和隔离图层

一、MapTool简介 在ArcGIS Pro SDK中&#xff0c;MapTool是一个重要的组件&#xff0c;用于自定义地图操作工具&#xff0c;使用户能够在ArcGIS Pro中执行特定的地图交互操作。 在VS中添加新项&#xff0c;可以找到ArcGIS Pro 地图工具&#xff0c;即为MapTool。 新建后打开c…

全连接网络实现回归【房价预测的数据】

也是分为data&#xff0c;model&#xff0c;train&#xff0c;test import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optimclass FCNet(nn.Module):def __init__(self):super(FCNet,self).__init__()self.fc1 nn.Linear(331,200)s…

​萝卜刀《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书

​萝卜刀《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书 ​萝卜刀《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书

mysql join语句优化实战

生产环境的大表join语句性能经常很差。这里给出大表join语句的优化思路。 准备材料 两张表&#xff0c;t1表N行&#xff0c;t2表M行 CREATE TABLE identity.t1 (id INT NOT NULL COMMENT Id,a INT NULL,PRIMARY KEY (id));CREATE TABLE identity.t2 (id INT NOT NULL COMMEN…

react create-react-app 配置less

环境信息&#xff1a; create-react-app:v5 react:18.2.0 node:18.16.0 如果你不必须使用 less 建议直接使用scss。 因为less配置会遇到很多问题。 配置less过程&#xff1a; 如果你只需要 sass的话&#xff0c;就可以直接使用sass。因为默认配置了scss。 npm、yarn、cnpm、…

wordpress搭建自己的博客详细过程以及踩坑

WordPress作为一款开源的内容管理系统&#xff08;CMS&#xff09;&#xff0c;具有诸多优势。首先&#xff0c;它的易用性使得即使对于没有编程经验的用户来说也能轻松上手&#xff0c;通过直观的用户界面和友好的管理工具&#xff0c;用户可以方便地创建、编辑和发布内容。其…

Mac 上没有 Total Commander,可以用这两款软件来代替

在 Windows 上&#xff0c;我用的最多的文件管理软件是 Total Commander&#xff0c;但转到 macOS 上却没有一款和它功能一样的软件&#xff0c;让人有些不爽。 经过一番搜寻&#xff0c;终于找到了 2 款可以部分代替 Total Commander 的软件&#xff0c;在此与大家分享。 1、…

竞赛选题 大数据疫情分析及可视化系统

文章目录 0 前言2 开发简介3 数据集4 实现技术4.1 系统架构4.2 开发环境4.3 疫情地图4.3.1 填充图(Choropleth maps)4.3.2 气泡图 4.4 全国疫情实时追踪4.6 其他页面 5 关键代码最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 大数据疫…

五、2023.10.1.C++stl.5

文章目录 65、请说说 STL 的基本组成部分?66、请说说 STL 中常见的容器&#xff0c;并介绍一下实现原理&#xff1f;67、请说说 STL 中常见的容器&#xff0c;并介绍一下实现原理&#xff1f;68、请你来介绍一下 STL 的空间配置器&#xff08;allocator&#xff09;&#xff1…

LabVIEW开发光学相干断层扫描系统

LabVIEW开发光学相干断层扫描系统 癌症是一种以异常或受损细胞无法控制生长为特征的疾病&#xff0c;是世界上导致死亡的主要原因之一。以前的研究人员已经表明&#xff0c;患病时组织力学会发生变化。能够同时量化和可视化组织力学和细胞行为有可能弥合我们对这两种癌症驱动特…

地理空间探测器保姆级教程-含实现程序-少理论多操作

1.实现软件excel程序 【传送门】 2.基本步骤 2.1 准备的数据样式 按省份地理位置&#xff0c;分为东中西三大板块 2.2 数据离散化 数据不需要标准化、归一化等X&#xff08;X可能多个&#xff09;数据&#xff0c;需要离散化&#xff0c;eg&#xff0c;使用门槛值&#x…

SLAM从入门到精通(tf的使用)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在ros的机器人学习过程中&#xff0c;有一件事情是肯定少不了的。那就是坐标系的转换。其实这也很容易理解。假设有一个机器人&#xff0c;它有一个…

竞赛选题 推荐系统设计与实现 协同过滤推荐算法

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 推荐系统设计与实现 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1…

Redis BitMap+SpringBoot 实现签到与统计功能

前言&#xff1a; 在各个项目中&#xff0c;我们都可能需要用到签到和 统计功能。签到后会给用户一些礼品以此来吸引用户持续在该平台进行活跃。 签到功能&#xff0c;使用 Redis 中的 BitMap 功能来实现&#xff0c;就是一个非常不错的选择。 一、Redis BitMap 基本用法 Bi…

Nat. Commun. | 大规模高分辨单光子成像

本文由论文作者团队(课题组)投稿 单光子雪崩二极管(Single Photon Avalanche Diode,简称SPAD)阵列因其极佳的单光子灵敏度而受到广泛关注,已广泛应用于量子通信与计算、荧光寿命成像、时间飞行成像等各个领域。与同样具有较高灵敏度的EMCCD和sCMOS相比,SPAD阵列能够在极…

搭建全连接网络进行分类(糖尿病为例)

拿来练手&#xff0c;大神请绕道。 1.网上的代码大多都写在一个函数里&#xff0c;但是其实很多好论文都是把网络&#xff0c;数据训练等分开写的。 2.分开写就是有一个需要注意的事情&#xff0c;就是要import 要用到的文件中的模型或者变量等。 3.全连接的回归也写了&#…

ubuntu下源码编译方式安装opencv

基础条件 ubuntu 20.04 opencv 3.4.3 opencv 源码编译的安装步骤 第一步&#xff0c; 首先clone源码 git clone https://github.com/opencv/opencv.git第二步&#xff0c;依赖包&#xff0c;执行下面的命令 sudo apt-get install build-essential sudo apt-get install cmak…

3.物联网射频识别,(高频)RFID应用ISO14443-2协议,(校园卡)Mifare S50卡

一。ISO14443-2协议简介 1.ISO14443协议组成及部分缩略语 &#xff08;1&#xff09;14443协议组成&#xff08;下面的协议简介会详细介绍&#xff09; 14443-1 物理特性 14443-2 射频功率和信号接口 14443-3 初始化和防冲突 &#xff08;分为Type A、Type B两种接口&…