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…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...