Compose | UI组件(十四) | Navigation-Data - 页面导航传递数据

文章目录

    • 前言
    • 传参流程
    • 实例说明
      • 普通方式传值
        • 定义接受参数格式
        • 定义接受参数类型
        • 获取参数
        • 传入参数
        • 传参和接受参数效果图
      • 结合 ViewModel 传递参数
        • 定义ViewModel
        • 在 navigation 定义 ViewModel 实例,并且传入 LoginScreen
        • 传入输入框中的值,并且跳转传值
        • 获取值
      • Parcelable 传递参数
        • 定义一个数据类
        • 自定义定义一个通用的NavType
        • 设置一个接受参数的占位符
        • 传递参数
        • 接收参数
    • 总结

前言

在 Compose 中使用 Navigation 组件进行页面跳转时,可以使用 NavController 和 NavHost 来传递参数。

传参流程

  1. 使用 NavController 传递参数:

NavController 是 Navigation 组件的核心类,用于控制页面导航。你可以在 NavController 中使用
navigate() 方法传递参数。这些参数可以在目标页面中通过参数名称获取并使用。

例如:

navController.navigate("SecondScreen") {  
    // 传递参数  
    arguments = remember { mutableStateOf("key") }  
    arguments?.putString("key", "value")  
}

在目标页面中,可以通过 arguments 参数获取传递的参数:

val value = arguments?.getString("key") ?: "default value"
  1. 使用 NavHost 传递参数:

在 NavHost 中,可以使用 composable() 函数定义导航路径和参数。在 composable()
函数中,可以指定传递的参数和接收参数的方法。

例如:

NavHost(navController = navController, startDestination = "MainScreen") {  
    composable("MainScreen") { MainScreen(arguments = listOf("value1", "value2")) }  
    composable("SecondScreen") { SecondScreen(arguments = listOf("value3", "value4")) }  
}

在目标页面中,可以通过 arguments 参数获取传递的参数:

val values = arguments[0] + arguments[1] // value1value2 for MainScreen, value3value4 for SecondScreen

这些是在 Compose 中使用 Navigation 组件进行参数传递的一些常见方法。具体实现可能因不同的平台、框架或技术而有所差异。

实例说明

下面使用登录页面传入用户名和密码,到详情页面,做为讲解案例

普通方式传值

就是通过 (状态)State 控制变量的传值

定义接受参数格式
object Detail:Screen(route = "$DETAIL?id={id},name={name},password={password}")

注:$DETAIL?id={id},name={name},password={password} 改为 $DETAIL/id={id},name={name},password={password}。将 ? 改为 / ,如果没有传值,程序就会崩溃,/ 默认是必填的,? 默认是选填的

定义接受参数类型
composable(route = Screen.Detail.route,
           arguments = listOf(
                navArgument(DETAIL_ARGUMENT_ID){
                    type = NavType.IntType
                    defaultValue = 0
                },
                navArgument(DETAIL_ARGUMENT_NAME){
                    type = NavType.StringType
                    defaultValue = "name is null"
                },
                navArgument(DETAIL_ARGUMENT_PASSWORD){
                    type = NavType.StringType
                    defaultValue = "password is null"
                }
           )
)

const val DETAIL_ARGUMENT_ID       = "id"
const val DETAIL_ARGUMENT_NAME     = "name"
const val DETAIL_ARGUMENT_PASSWORD = "password"
获取参数
composable(route = Screen.Detail.route,
           ...){navBackStackEntry ->
	    val id    = navBackStackEntry.arguments?.getInt("id") ?: 0
	    val name  = navBackStackEntry.arguments?.getString("name") ?: ""
	    val password   = navBackStackEntry.arguments?.getString("password") ?: ""
	    DetailScreen(id,name,password,navController = navController)
}
传入参数
object Detail:Screen(route = "..."){

    fun passIdAndName(id:Int= 0,name:String="tanZuAi",password:String="tanZuAi123"):String{
        return "$DETAIL?id=${id},name=${name},password=${password}"
    }
}

navController.navigate(Screen.Detail.passIdAndName())
传参和接受参数效果图

navigation传参和接受参数效果图

至此,基本的传参,就已经可以实现了

结合 ViewModel 传递参数

就是通过结合 ViewModel 传参

定义ViewModel

LoginViewModel.kt

class LoginViewModel: ViewModel(){
    var nameText by mutableStateOf("")

    fun onTextChanged(newString:String){
        nameText = newString
    }
}
在 navigation 定义 ViewModel 实例,并且传入 LoginScreen
navigation(startDestination = Screen.Login.route,route = AUTHENTICATION_ROUTE){
		   composable(route = Screen.Login.route){
		        val loginViewModel = viewModel<LoginViewModel>()
		        LoginScreen(loginViewModel,navController  = navController)
		    }
		    composable(route = Screen.Signup.route){
		        SignUpScreen(navController = navController)
		    }
}
传入输入框中的值,并且跳转传值

LoginScreen.kt

//定义ViewModel 参数
fun LoginScreen(loginViewModel:LoginViewModel = viewModel(), navController: NavController)

  //注释掉状态定义的变量值
//var textName by remember { mutableStateOf("") }
//监听输入框的值,并且改变viewmodel变量的值
OutlinedTextField(value = loginViewModel.nameText,
    onValueChange = {
        loginViewModel.onTextChanged(it)
    },
    label = { Text(text = stringResource(id = R.string.app_user_name)) },
    modifier = Modifier.fillMaxWidth()
)

//传值给name
navController.navigate(Screen.Detail.passIdAndName(name = loginViewModel.nameText))
获取值

Screen.kt

object Detail:Screen(route = "$DETAIL?id={id},name={name},password={password}"){
    fun passIdAndName(id:Int= 0,name:String="tanZuAi",password:String="tanZuAi123"):String{
        return "$DETAIL?id=${id},name=${name},password=${password}"
    }
}

HomeNavGraph.kt

val name  = navBackStackEntry.arguments?.getString("name") ?: ""

DetailScreen(id,name,password,navController = navController)

DetailScreen.kt

Text(modifier = Modifier.clickable {},
           text  = "Detail_Name: $name" ,
           color = Color.Red,
           style = MaterialTheme.typography.bodyLarge)

至此,结合 ViewModel 传值流程已经讲完了

Parcelable 传递参数

通过Parcelable传递一个对象数据

定义一个数据类
@Parcelize
data class EmailModel(val id:Int,var name:String,var password:String):Parcelable
自定义定义一个通用的NavType
inline fun <reified T : Parcelable> createParcelableNavType(isNullableAllowed: Boolean = false): NavType<T> {
    return object : NavType<T>(isNullableAllowed) {

        override val name: String
            get() = "SupportParcelable"

        override fun get(bundle: Bundle, key: String): T? {  //从Bundle中检索 Parcelable类型
            return bundle.getParcelable(key)
        }

        override fun parseValue(value: String): T {  //定义传递给 String 的 Parsing 方法
            return Gson().fromJson(value, T::class.java)
        }

        override fun put(bundle: Bundle, key: String, value: T) {  //作为 Parcelable 类型添加到 Bundle
            bundle.putParcelable(key, value)
        }

    }
}

navArgument("jsonParcelable"){
    type = createParcelableNavType<EmailModel>()
}
设置一个接受参数的占位符
object Detail:Screen(route = "$DETAIL?key={jsonParcelable}")
传递参数
fun passIdAndName(id:Int= 0,name:String="tanZuAi",password:String="tanZuAi123"):String{
    val jsonParcelable = Gson().toJson(EmailModel(id,name, password))
    return "$DETAIL?key=${Uri.encode(jsonParcelable)}"
}
接收参数
val emailModel = navBackStackEntry.arguments?.getParcelable<EmailModel>("jsonParcelable")

emailModel?.apply {
    DetailScreen(id,name,password,navController = navController)
}

注:至此,通过 Parcelable 传递对象数据就讲完了

总结

  1. 普通方式传值:$DETAIL?id={id},name={name},password={password}
  2. ViewModel传值:继承 ViewModel() 类,在类中定义状态变量,通过监听变量值变化,获取变量值
  3. Parcelable传值:通过 Gson().toJson() 转换对象,传递值

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Arthas使用教程—— 阿里开源线上监控诊断产品

文章目录 1 简介2背景3 图形界面工具 arthas 阿里开源3.1 &#xff1a;启动 arthas3.2 help :查看arthas所有命令3.3 查看 dashboard3.4 thread 列出当前进程所有线程占用CPU和内存情况3.5 jvm 查看该进程的各项参数 &#xff08;类比 jinfo&#xff09;3.6 通过 jad 来反编译 …

React+Antd实现省、市区级联下拉多选组件(支持只选省不选市)

1、效果 是你要的效果&#xff0c;咱们继续往下看&#xff0c;搜索面板实现省市区下拉&#xff0c;原本有antd的Cascader组件&#xff0c;但是级联组件必须选到子节点&#xff0c;不能只选省&#xff0c;满足不了页面的需求 2、环境准备 1、react18 2、antd 4 3、功能实现 …

Win32 SDK Gui编程系列之--ListView自绘OwnerDraw(续)

通过所有者绘制的列表视图(2) 所有者绘制列表视图的基础已在前一页中说明。本页将展示如何在所有者绘制列表视图中显示数据库表数据。 1、访问日志 正如在另一个页面中所述,本网站的访问日志目前是通过SQLite3数据库管理的。 以下是上述程序执行的结果。为…

OpenCV-30 腐蚀操作

一、引入 腐蚀操作也是用卷积核扫描图像&#xff0c;只不过腐蚀操作的卷积核一般都是1&#xff08;卷积核内的每个数字都为1&#xff09;&#xff0c;如果卷积核内所有像素点都是白色&#xff0c;那么锚点&#xff08;中心点&#xff09;即为白色。 大部分时候腐蚀操作使用的都…

基于ESP-WROOM-32的双串口通信并显示到OLED显示屏上

目录 开发板引脚图 Arduino环境配置1.ESP32开发版下载2.Arduino开发板选择 -> ESP32 Dev Module3.安装驱动库 接线图Arduino代码现象演示 开发板 ESP-WROOM-32 引脚图 Arduino环境配置 1.ESP32开发版下载 选择 esp32 by Espressif Systems 2.Arduino开发板选择 -> E…

搜索引擎DuckDuckGo代理指南

DuckDuckGo作為一款搜索引擎&#xff0c;同時擁有自己的流覽器&#xff0c;高度保護用戶隱私&#xff0c;使其有別於其他收集和利用用戶數據進行定向廣告的搜索引擎。然而&#xff0c;單獨使用DuckDuckGo並不能保證線上完全匿名。如果你想進一步保護隱私&#xff0c;那就需要使…

寒假作业5

TCP 1&#xff1a;提供面向连接的&#xff0c;可靠的数据传输服务 2&#xff1a;传输过程中&#xff0c;数据无误、数据无丢失、数据无失序、数据无重复 3&#xff1a;数据传输效率低&#xff0c;耗费资源多 4&#xff1a;数据收发是不同步的 5&#xff1a;TCP的使用场景&#…

【计算机网络】【练习题及解答】【新加坡南洋理工大学】【Computer Control Network】【Exercise Solution】

说明&#xff1a; 个人资料&#xff0c;仅供学习使用&#xff0c;版权归校方所有。 一、题目描述 该问题接上期博文【练习题及解答】&#xff0c;描述网络通信中的链路效率&#xff08;Link Efficiency&#xff09;&#xff0c;即Link Utilization的计算。&#xff08;此处认…

go modules使用

创建项目 在使用GoLand创建项目的时候&#xff0c;会自动创建对应的go.mod文件。 创建完后 创建文件 创建一个main.go的文件&#xff0c;里面print一个hello world。 在运行时可以设置是否采取先生成文件再运行。 为空的话则不输出。 下面的Environment为设置运行的环境…

IDEA生成可执行jar包

1. 进入需要打包的项目&#xff0c;选择 最上方菜单栏的 File → Project Structure 2. 选择 左侧菜单栏 Artifacts → 加号 → JAR → from modules with dependencies 3. 选择入口类 Main Class&#xff08;点击文件夹图标可以快速选择&#xff09;&#xff0c;点击 OK&#…

万物皆可问 — 私有部署网易有道QAnything

什么是 QAnything&#xff1f; QAnything&#xff08;Question and Answer based on Anything&#xff09;是一个本地知识库问答系统&#xff0c;旨在支持多种文件格式和数据库&#xff0c;允许离线安装和使用。使用QAnything&#xff0c;您可以简单地删除本地存储的任何格式的…

人工智能|深度学习——使用多层级注意力机制和keras实现问题分类

代码下载 使用多层级注意力机制和keras实现问题分类资源-CSDN文库 1 准备工作 1.1 什么是词向量? ”词向量”&#xff08;词嵌入&#xff09;是将一类将词的语义映射到向量空间中去的自然语言处理技术。即将一个词用特定的向量来表示&#xff0c;向量之间的距离&#xff08;例…

Web 站点的欢迎页面

Web 站点的欢迎页面 一、JavaWeb 中的欢迎页1.Tomcat 的默认欢迎页2.局部配置欢迎页 二、SpringBoot 中的欢迎页1.默认欢迎页2.自定义欢迎页(1) 通过页面跳转控制器方式(2) controller 直接实现方式 一、JavaWeb 中的欢迎页 1.Tomcat 的默认欢迎页 当文件名设置为 index.html…

【学习笔记】TypeScript学习笔记1 --TypeScript中的类型

文章目录 TS总的变量类型References TS总的变量类型 备注&#xff1a; 如果一个变量设置为了any 类型之后相当于变量关闭了TS的类型检测 let d: any; d 10; d hello;//unknown表示的是未知类型&#xff0c;实际是上一个安全的any,unknown类型的变量不能直接赋值给其他变量le…

Avalonia学习(二十三)-大屏

弄一个大屏显示的界面例子&#xff0c;但是代码有点多&#xff0c;还有用户控件。 目前还有一点问题在解决&#xff0c;先看一下界面效果。

mybatis sql报错记录: Encountered “<EOF>“ at line 1, column 0.

报错日志&#xff1a; 解决问题&#xff1a; ***<if test" ">***AND T1.xxx_code in<foreach item"pollCode" collection"vo.pollCodeList" open"(" separator"," close")">#{pollCode}</foreac…

宝塔面板Node项目带参启动配置方法

宝塔面板Node项目带参启动配置方法 ​0x00 缘起​0x01 解决方法​0x02 系统信息​0x03 后记 ​0x00 缘起 编写的Nest项目根据启动时的环境变量加载不同的数据库配置, 在CentOS 7的终端中, 使用如下命令就可以启动成功: export NODE_ENVproduction; node dist/main可是使用宝塔…

宠物空气净化器适合养猫家庭吗?除猫毛好的猫用空气净化器推荐

宠物掉毛是一个普遍存在的问题&#xff0c;尤其在脱毛季节&#xff0c;毛发似乎无处不在。这给家中的小孩和老人带来了很多麻烦&#xff0c;他们容易流鼻涕、过敏等不适。此外&#xff0c;宠物有时还会不规矩地拉扯和撒尿&#xff0c;这股气味实在是难以忍受。家人们对宠物的存…

数据结构第十三天(树)

目录 前言 概述 树的基本概念&#xff1a; 树的相关操作 &#xff1a; 源码&#xff1a; 主函数&#xff1a; 运行结果&#xff1a; 往期精彩内容&#xff1a; 前言 2010年一部电影创造了奇迹&#xff0c;它是全球第一部票房到达 27 亿美 元&#xff0c;总票房历史 排名第…

Linux系统调试课:硬件断点

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢在linux内核编程中,经常会遇到由于内存被篡改,例如 buffer overflow,野指针,write after free等。查找分析此类问题非常的麻烦。 一、什么是硬件断点 硬件断点,是Linux内核中是一种被ptrace和内核内调试器使用调试…