Android Jetpack Compose入门教程(二)
一、列表和动画
列表和动画在应用内随处可见。在本课中,您将学习如何利用 Compose 轻松创建列表并添加有趣的动画效果。
1、创建消息列表
只包含一条消息的聊天略显孤单,因此我们将更改对话,使其包含多条消息。您需要创建一个可显示多条消息的 Conversation 函数。对于此用例,请使用 Compose 的 LazyColumn 和 LazyRow。这些可组合项只会呈现屏幕上显示的元素,因此,对于较长的列表,使用它们会非常高效。
@Composable
fun Conversation(messages: List<Message>) {LazyColumn {items(messages.size) { index ->MessageCard(messages[index])}}
}@Preview(showBackground = true)
@Composable
fun PreviewConversation() {Compose_DemoTheme {Conversation(messages = SampleData.conversationSample)}
}object SampleData{val conversationSample = listOf(Message("Lexi","Test...Test,,,Test,,,"),Message("Lexi","只包含一条消息的聊天略显孤单。"),Message("Lexi","因此我们将更改对话,使其包含多条消息。您需要创建一个可显示多条消息的 Conversation 函数"),Message("Lexi","对于此用例,请使用 Compose 的 LazyColumn 和 LazyRow。这些可组合项只会呈现屏幕上显示的元素,因此,对于较长的列表,使用它们会非常高效"),Message("Lexi","在此代码段中"),Message("Lexi","您可以看到 LazyColumn 包含一个 items 子项"),Message("Lexi","它接受 List 作为参数,并且其 lambda 会收到我们命名为 message 的参数(可以随意为其命名),该参数是 Message 的实例"),Message("Lexi","简而言之,系统会针对提供的 List 的每个项调用此 lambda"),Message("Lexi","将示例数据集复制到您的项目中,以便快速引导对话"),)
}
在此代码段中,您可以看到 LazyColumn 包含一个 items 子项。它接受 List 作为参数,并且其 lambda 会收到我们命名为 index的参数(可以随意为其命名),该参数是 List的index。简而言之,系统会针对提供的 List 的每个项调用此 lambda。将示例数据集复制到您的项目中,以便快速引导对话。
2、在展开消息时显示动画效果
对话变得更加有趣了。是时候添加动画效果了!您将添加展开消息以显示更多内容的功能,同时为内容大小和背景颜色添加动画效果。为了存储此本地界面状态,您需要跟踪消息是否已展开。为了跟踪这种状态变化,您必须使用 remember 和 mutableStateOf 函数。
可组合函数可以使用 remember 将本地状态存储在内存中,并跟踪传递给 mutableStateOf 的值的变化。该值更新时,系统会自动重新绘制使用此状态的可组合项(及其子项)。这称为重组。
通过使用 Compose 的状态 API(如 remember 和 mutableStateOf),系统会在状态发生任何变化时自动更新界面。
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
// enableEdgeToEdge()setContent {Compose_DemoTheme {Conversation(messages = SampleData.conversationSample)}}}
}@Composable
fun Conversation(messages: List<Message>) {LazyColumn {items(messages.size) { index ->MessageCard(messages[index])}}
}@Composable
fun MessageCard(msg: Message) {Row(modifier = Modifier.padding(all = 8.dp)) {Image(painter = painterResource(id = R.drawable.ic_android_logo),contentDescription = "Contact profile picture",modifier = Modifier.size(40.dp).clip(CircleShape).border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape))Spacer(modifier = Modifier.width(8.dp))//We keep track if the message is expanded or not in this//variablevar isExpanded by remember { mutableStateOf(false) }Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {Text(text = msg.author,color = MaterialTheme.colorScheme.secondary,style = MaterialTheme.typography.titleSmall)Spacer(modifier = Modifier.width(4.dp))Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) {Text(text = msg.body,modifier = Modifier.padding(all = 4.dp),// If the message is expanded, we display all its content// otherwise we only display the first linemaxLines = if (isExpanded) Int.MAX_VALUE else 1,style = MaterialTheme.typography.bodyMedium)}}}
}
注意:您需要添加以下导入内容才能正确使用 Kotlin 的委托属性语法(by 关键字)。按 Alt+Enter 或 Option+Enter 即可添加这些内容。
import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue
3、更改消息内容的背景颜色
现在,您可以根据点击消息时消息的 isExpanded 状态,更改消息内容的背景颜色。您将使用 clickable 修饰符来处理可组合项上的点击事件。您会为背景颜色添加动画效果,使其值逐步从 MaterialTheme.colorScheme.surface 更改为 MaterialTheme.colorScheme.primary(反之亦然),而不只是切换 Surface 的背景颜色。为此,您将使用 animateColorAsState 函数。最后,您将使用 animateContentSize 修饰符顺畅地为消息容器大小添加动画效果:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
// enableEdgeToEdge()setContent {Compose_DemoTheme {Conversation(messages = SampleData.conversationSample)}}}
}@Composable
fun Conversation(messages: List<Message>) {LazyColumn {items(messages.size) { index ->MessageCard(messages[index])}}
}@Composable
fun MessageCard(msg: Message) {Row(modifier = Modifier.padding(all = 8.dp)) {Image(painter = painterResource(id = R.drawable.ic_android_logo),contentDescription = "Contact profile picture",modifier = Modifier.size(40.dp).clip(CircleShape).border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape))Spacer(modifier = Modifier.width(8.dp))//We keep track if the message is expanded or not in this//variablevar isExpanded by remember { mutableStateOf(false) }val surfaceColor by animateColorAsState(if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface,)Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {Text(text = msg.author,color = MaterialTheme.colorScheme.secondary,style = MaterialTheme.typography.titleSmall)Spacer(modifier = Modifier.width(4.dp))Surface(shape = MaterialTheme.shapes.medium,shadowElevation = 1.dp,color = surfaceColor,modifier = Modifier.animateContentSize().padding(1.dp)) {Text(text = msg.body,modifier = Modifier.padding(all = 4.dp),// If the message is expanded, we display all its content// otherwise we only display the first linemaxLines = if (isExpanded) Int.MAX_VALUE else 1,style = MaterialTheme.typography.bodyMedium)}}}
}
二、后续步骤
恭喜,您已完成 Compose 教程!您已高效地构建了一个简单的聊天界面,该界面显示包含图片和文字的可展开动画消息列表,使用 Material Design 原则设计,添加了深色主题且具有预览功能,所有内容只需不到 100 行代码!
以下是您目前为止所学的内容:
- 定义可组合函数
- 在可组合项中添加不同的元素
- 使用布局可组合项构建界面组件
- 使用修饰符扩展可组合项
- 创建高效列表
- 跟踪状态以及修改状态
- 在可组合项上添加用户互动
- 在展开消息时显示动画效果
Compose官方中文课程
Jetpack Compose 官方使用入门
相关文章:

Android Jetpack Compose入门教程(二)
一、列表和动画 列表和动画在应用内随处可见。在本课中,您将学习如何利用 Compose 轻松创建列表并添加有趣的动画效果。 1、创建消息列表 只包含一条消息的聊天略显孤单,因此我们将更改对话,使其包含多条消息。您需要创建一个可显示多条消…...

如何避免接口重复请求(axios推荐使用AbortController)
前言: 我们日常开发中,经常会遇到点击一个按钮或者进行搜索时,请求接口的需求。 如果我们不做优化,连续点击按钮或者进行搜索,接口会重复请求。 以axios为例,我们一般以以下几种方法为主: 1…...
算法设计与分析:网络流求解棒球赛淘汰问题C++
目录 一、实验目的 二、问题描述 三、实验要求 四、算法思想 1、明显的:win[i]+remain[i][j]<> 2、不明显的:最大流 3、操作 3.1 先读入相关信息(邻接矩阵**k),进行一遍“明显的”判断。 3.2 对剩下的“不明显的”的每个球队构建流网络(邻接表vector< ve…...
Linux Ubuntu 24.04 C语言gcc编译过程详解
下面是Hello World程序源代码文件hello.c的内容,我们将以它为例来说明源文件到可执行文件的形成过程,主要分4步:预处理、汇编、机器码、链接。 #include <stdio.h> int main () {printf ( "hello, world \n " );return 0; }…...
Python自动化办公篇—pandas操作Excel:读取+查看+选择+清洗+排序+筛选+函数+写入
目录 专栏导读库的介绍库的安装1、读取数据2、查看数据3、选择数据4、数据清洗5、数据排序6、数据筛选7、数据操作8、数据写入总结 专栏导读 文章名称链接Python自动化办公—pyautogui图像定位\点击功能,实现自动截取当前屏幕并检索点击(可制作为游戏点击脚本)点我进行跳转Pyt…...

数据库大作业——音乐平台数据库管理系统
W...Y的主页😊 代码仓库分享💕 《数据库系统》课程设计 :流行音乐管理平台数据库系统(本数据库大作业使用软件sql server、dreamweaver、power designer) 目录 系统需求设计 数据库概念结构设计 实体分析 属性分…...

【DBA早下班系列】—— 并行SQL/慢SQL 问题该如何高效收集诊断信息
1. 前言 OceanBase论坛问答区或者提交工单支持的时候大部分时间都浪费在了诊断信息的获取交互上,今天我就其中大家比较头疼的SQL问题,给大家讲解一下如何一键收集并行SQL/慢SQL所需要的诊断信息,减少沟通成本,让大家早下班。 2. …...

用python实现多文件多文本替换功能
用python实现多文件多文本替换功能 今天修改单位项目代码时由于改变了一个数据结构名称,结果有几十个文件都要修改,一个个改实在太麻烦,又没有搜到比较靠谱的工具软件,于是干脆用python手撸了一个小工具,发现python在…...

【DevOps】深入探索Ubuntu操作系统:全面了解
引言 在开源软件的世界里,Ubuntu是一个闪耀的明星。它不仅是一个操作系统,更是一种社区精神、一种共享和协作的文化。Ubuntu操作系统基于强大的Linux内核,由世界各地的开发者共同维护和改进。在这篇博文中,我们将深入探索Ubuntu操…...

【Linux】—MySQL安装
文章目录 前言一、下载官方MySQL包二、下载完成后,通过xftp6上传到Linux服务器上三、解压MySQL安装包四、在安装目录下执行rpm安装,请按顺序依次执行。五、配置MySQL六、启动MySQL数据库七、退出,重新登录数据库 前言 本文主要介绍在Linux环境…...
【vue】form表单提交validate验证不进valid原因
目录 1. 原因 1. 原因 1.<el-form>是否写了ref“form”。2.是否有其它标签写了ref“form”。3.<el-form>中要写成:model,不能使用v-model。4.自定义的validate要各个路径均能返回callback()。 const validatePass (rule, value, callback) > {if (…...

如何用 Google Chrome 浏览器浏览经过 XSLT 渲染的 XML 文件
对于经过XSLT渲染的XML文件,本来,可以直接用 IE (Internet Explorer) 打开,就能看到渲染之后的样子,很方便。但是后来,微软把 IE 换成了 Microsoft Edge,按理说这是比 IE 更先进的浏览器,可是偏…...

Python学习笔记12:进阶篇(二),类的继承与组合
类的继承 我们在编写一系列的类的时候,会发现这些类很相似,但是又有各自的特点和行为。在编写这些类的时候,我们可以把相同的部分抽象成一个基类,然后根据其他不同的特点和行为,抽象出子类,继承这个基类。…...

npm install cnpm -g 报错4048
npm install cnpm -g 报错4048 设置淘宝镜像: 报错如下: 其他博主提供的方法都尝试了,比如管理员权限打开终端,删除.npmrc文件,清除缓存npm cache clean -f等都试了无效,最后怀疑是npm和cnpm版本不对应&…...

本地快速部署 SuperSonic
本地快速部署 SuperSonic 0. 引言1. 本地快速部署 supersonic2. 访问 supersonic3. 支持的数据库4. github 地址 0. 引言 SuperSonic融合Chat BI(powered by LLM)和Headless BI(powered by 语义层)打造新一代的BI平台。这种融合确…...
如何给vue开发的网站做seo?
最近公司有个需求,需要给公司的官网sqlynx做seo,但因为各种历史原因吧,原来的网站是用vue开发的。没办法,只能尝试尽量做一些seo,让网站能更好一些。 目录 1. 服务器端渲染(SSR) 2. 预渲染&am…...

算法训练营第六十天(延长12天添加图论) | LeetCode 647 回文子串、LeetCode 516 最长回文子序列
LeetCode 67 回文子串 思路很简单,每一个dp[i]等于dp[i-1]加上当前字符向前直到0各个长度字符串回文串个数即可 代码如下: class Solution {public boolean isValid(String s) {int l 0, r s.length() - 1;while (l < r) {if (s.charAt(l) ! s.ch…...

TikTok账号养号的流程分享
对于很多刚开始运营TikTok的新手小白来说,都会有一个同样的疑问,那就是:TikTok到底需不需要养号?这里明确告诉大家是需要养号的,今天就把我自己实操过的养号经验和策略总结出来,分享给大家。 一、什么是Ti…...

C++初学者指南第一步---6.枚举和枚举类
C初学者指南第一步—6.枚举和枚举类 文章目录 C初学者指南第一步---6.枚举和枚举类1.作用域的枚举(enum class类型)(C11)2.无作用域的枚举(enum类型)3.枚举类的基础类型4.自定义枚举类映射5.和基础类型的互相转换 1.作用域的枚举(enum class类…...
【js判断机型】
var isIOS /(iPhone|iPad|iPod)/i.test(navigator.userAgent) var isiPad navigator.userAgent.match(/(iPad)/) || (navigator.platform ‘MacIntel’ && navigator.maxTouchPoints > 1) 上面这个不行的话,再试下这个 var isiPad (navigator.userAg…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...

云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
起重机起升机构的安全装置有哪些?
起重机起升机构的安全装置是保障吊装作业安全的关键部件,主要用于防止超载、失控、断绳等危险情况。以下是常见的安全装置及其功能和原理: 一、超载保护装置(核心安全装置) 1. 起重量限制器 功能:实时监测起升载荷&a…...