Android的Compose
Jetpack Compose 是用于构建原生 Android 界面的新工具包,无需修改任何 XML 布局,也不需要使用布局编辑器。相反,只需调用可组合函数来定义所需的元素,Compose 编译器即会完成后面的所有工作。
简而言之,使用Compose,不再需要xml编写页面。
可组合函数(Composable function)
Compose是围绕可组合函数构建的,只需要描述应用界面的外观并提供数据依赖,而不必关注界面的构建过程(如初始化元素、将其附加到父项等)。而创建Composable function,只需要添加注解@Composable到函数名称前。
首先,我们构建创建一个应用:ComposeTutorial。在AS中选择Empty Activity创建。
添加文本元素
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {//在此处定义布局//此处的Text方法是由Compose界面库定义的文本Composable functionText("Hello world!")}}
}
setContent块定义了activity的布局,在此处我们添加了Text即“Hello World!”。
自定义可组合函数
如果需要将一个函数转换为Composable function,我们需要添加注解“@Composable”。
修改MainActivity:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {MessageCard("Android")//使用我们自定义的Composable function}}
}@Composable//添加注解,使该函数成为Composable function
fun MessageCard(name: String) {Text(text = "Hello $name!")
}
在AS中预览Composable function
借助@Preview注解,可以在AS中预览Composable function,无需安装到设备或虚拟器中。
唯一要求是该注解不能用于接收参数的函数中,因此在MainActivity新增如下函数:
@Preview
@Composable
fun PreviewMessageCard() {MessageCard("Android")
}
在重新构建后,该函数没有被调用,应用本身不会改变,但是AS对于所有添加了@Preview注解的界面元素可以进行预览,点击如下两个按钮之一即可:
布局(Layout)
在此处我们实现一个简单的聊天界面,显示发送者和消息内容,点击消息时可缩放。
添加多个文本
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {//向Composable function中传入发送者名称和消息内容 MessageCard(Message("Android", "Jetpack Compose"))}}
}//新建一个Message类,包含消息发送者和消息内容
data class Message(val author: String, val body: String)@Composable
fun MessageCard(msg: Message) {Text(text = msg.author)Text(text = msg.body)
}@Preview
@Composable
fun PreviewMessageCard() {MessageCard(msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!"))
}
这段代码会在内容视图中创建两个文本元素。不过,由于未提供有关如何排列这两个文本元素的信息,因此它们会相互重叠,使文本无法阅读。
使用Column、Row、Box
Column,直译为“圆柱体、长列”。
使用该函数修改MessageCard,可以垂直排列元素,使其不再重叠文本。
@Composable
fun MessageCard(msg: Message) {Column {Text(text = msg.author)Text(text = msg.body)}
}
同样的,可以使用Row函数水平排列元素,而使用Box函数可以堆叠元素。
添加图片元素
使用Resource Manager从照片库中导入图片,修改MessageCard:
@Composable
fun MessageCard(msg: Message) {//使用Row方法,水平排列图片和消息Row {Image(painter = painterResource(R.drawable.profile_picture),contentDescription = "Contact profile picture",)Column {Text(text = msg.author)Text(text = msg.body)}}}
配置布局(Modifier)
使用修饰符(Modifier)实现。
Compose中的每一个组件都具有Modifier属性,通过他我们可以设置组件的大小、间距、外观,甚至添加互动事件,如点击、触摸事件。
@Composable
fun MessageCard(msg: Message) {//在消息周围添加8dp的距离Row(modifier = Modifier.padding(all = 8.dp)) {Image(painter = painterResource(R.drawable.profile_picture),contentDescription = "Contact profile picture",modifier = Modifier//设置图片大小.size(40.dp)//将图片修剪为圆形.clip(CircleShape))//在图片和消息之间添加一个水平的空间(Spacer),间距为8dpSpacer(modifier = Modifier.width(8.dp))Column {Text(text = msg.author)// 在发送者和消息内容之间添加一个垂直的空间Spacer(modifier = Modifier.height(4.dp))Text(text = msg.body)}}
}
Material Design
Compose 旨在支持 Material Design 原则。它的许多界面元素都原生支持 Material Design。
使用
Jetpack Compose 原生提供 Material Design 3 及其界面元素的实现。我们使用 Material Design 样式改进MessageCard可组合项的外观。
在创建ComposeTutorial项目时,会同时创建一个名为“ComposeTutorialTheme”的Material主题,和一个来自Material Design 3的“Surface”。我们将用到这两位来封装MessageCard函数。
Material Design是围绕Color、Typography、Shape来构建的,我们将逐一添加这些元素。
修改MainActivity:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {//使用ComposeTutorialTheme和Surface封装MessageCard函数ComposeTutorialTheme {//将给定的组件或布局填满父容器的界面Surface(modifier = Modifier.fillMaxSize()) {MessageCard(Message("Android", "Jetpack Compose"))}}}}
}@Preview
@Composable
fun PreviewMessageCard() {//在@Preview中也要封装,沿用应用主题中定义的样式,保持统一ComposeTutorialTheme {Surface {MessageCard(msg = Message("Lexi", "Take a look at Jetpack Compose, it's great!"))}}
}
颜色
@Composable
fun MessageCard(msg: Message) {Row(modifier = Modifier.padding(all = 8.dp)) {Image(painter = painterResource(R.drawable.profile_picture),contentDescription = null,modifier = Modifier.size(40.dp).clip(CircleShape)//为图像增加一个圆框.border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape))Spacer(modifier = Modifier.width(8.dp))Column {Text(text = msg.author,//通过MaterialTheme.colorScheme,使用已封装主题中的颜色设置样式color = MaterialTheme.colorScheme.secondary)Spacer(modifier = Modifier.height(4.dp))Text(text = msg.body)}}
}
Typography(排版)
MaterialTheme
中提供了 Material Typography 样式,只需将其添加到 Text
可组合项中即可。
@Composable
fun MessageCard(msg: Message) {Row(modifier = Modifier.padding(all = 8.dp)) {Image(painter = painterResource(R.drawable.profile_picture),contentDescription = null,modifier = Modifier.size(40.dp).clip(CircleShape).border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape))Spacer(modifier = Modifier.width(8.dp))Column {Text(text = msg.author,color = MaterialTheme.colorScheme.secondary,style = MaterialTheme.typography.titleSmall)Spacer(modifier = Modifier.height(4.dp))Text(text = msg.body,style = MaterialTheme.typography.bodyMedium)}}
}
Shape(形状)
@Composable
fun MessageCard(msg: Message) {Row(modifier = Modifier.padding(all = 8.dp)) {Image(painter = painterResource(R.drawable.profile_picture),contentDescription = null,modifier = Modifier.size(40.dp).clip(CircleShape).border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape))Spacer(modifier = Modifier.width(8.dp))Column {Text(text = msg.author,color = MaterialTheme.colorScheme.secondary,style = MaterialTheme.typography.titleSmall)Spacer(modifier = Modifier.height(4.dp))//将消息详情封装在Surface中,此时可自定义消息详情的大小、形状等布局Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) {Text(text = msg.body,modifier = Modifier.padding(all = 4.dp),style = MaterialTheme.typography.bodyMedium)}}}
}
启用深色主题
又称夜间模式。由于支持Material Design,Jetpack Compose默认能够处理深色主题。
使用Material Design颜色、文本和背景时,系统会自动适应深色背景。
//可以在文件中以单独函数的形式创建多个预览,也可以向同一个函数中添加多个注解
@Preview(name = "Light Mode")
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES,showBackground = true,name = "Dark Mode"
)
@Composable
fun PreviewMessageCard() {ComposeTutorialTheme {Surface {MessageCard(msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!"))}}
}
列表和动画
创建消息列表(LazyColumn、LazyRow)
LazyColumn、LazyRow是Compose常见的两个组件,他们的优点是可以延迟加载。他们只会加载当前可见的列表项,并在滚动时动态回收其他项,这使得他们适用于展示大量数据或无限滚动的列表。
在使用中,会包含一个items子项。他接受LIst作为参数,并且其lambda会接收到参数。系统会针对提供的List的每个项调用此lambda。
@Composable
fun Conversation(messages: List<Message>) {LazyColumn {//items子项items(messages) { message ->MessageCard(message)}}
}@Preview
@Composable
fun PreviewConversation() {ComposeTutorialTheme {Conversation(SampleData.conversationSample)}
}
在展开消息时显示动画效果
为了存储某条消息是否已展开,我们使用remember和mutableStateOf函数。
可组合函数可以使用remember将本地状态存储到内存中,并跟踪传递给mutableStateOf的值的变化。而mutableStateOf函数可以在可组合函数内部创建一个可变的状态,并将其与UI组件进行绑定。当状态值发生变化时,Compose会自动重绘相关的组件。
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {ComposeTutorialTheme {Conversation(SampleData.conversationSample)}}}
}@Composable
fun MessageCard(msg: Message) {Row(modifier = Modifier.padding(all = 8.dp)) {Image(painter = painterResource(R.drawable.profile_picture),contentDescription = null,modifier = Modifier.size(40.dp).clip(CircleShape).border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape))Spacer(modifier = Modifier.width(8.dp))// 在此变量中,跟踪当前消息是否展开var 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.height(4.dp))Surface(shape = MaterialTheme.shapes.medium,shadowElevation = 1.dp,) {Text(text = msg.body,modifier = Modifier.padding(all = 4.dp),// 若展开,全部显示;不展开,最大显示一行maxLines = if (isExpanded) Int.MAX_VALUE else 1,style = MaterialTheme.typography.bodyMedium)}}}
}
注:需要添加以下导入内容才能正确使用 Kotlin 的委托属性语法(
by
关键字):import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
使用by关键字是避免每次都访问value属性的好方法。
同时需要注意的是,我们应该只在可组合函数的作用域之外改变状态。这是因为可组合项可以频繁运行、且以任何顺序执行。此处我们可以在clickable中修改isExpanded的值,是因为clickable不是可组合函数。
除了remember关键字,我们还可以使用rememberSaveable,它与前者类似,但存储的值可以在重新创建activity和进程后保存下来。需要注意的是,rememberSaveable适用于UI状态,如购物车的商品数量或选定的标签页,但不适用于过渡动画状态等。
同时我们可以加入颜色,在消息缩放时改变消息的颜色。但不能只是简单的改变消息的背景颜色,我们应当加入动画,使得变化时逐步更改。
相同的,在点击缩放时,我们也可以加上动画,使得缩放更加顺滑。
@Composable
fun MessageCard(msg: Message) {Row(modifier = Modifier.padding(all = 8.dp)) {Image(painter = painterResource(R.drawable.profile_picture),contentDescription = null,modifier = Modifier.size(40.dp).clip(CircleShape).border(1.5.dp, MaterialTheme.colorScheme.secondary, CircleShape))Spacer(modifier = Modifier.width(8.dp))var isExpanded by remember { mutableStateOf(false) }// 该变量会逐步更新颜色,animateColorAsState函数实现颜色之间的过渡动画效果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.height(4.dp))Surface(shape = MaterialTheme.shapes.medium,shadowElevation = 1.dp,color = surfaceColor,//加入animateContentSize,给缩放加入动画,更加顺滑modifier = Modifier.animateContentSize().padding(1.dp)) {Text(text = msg.body,modifier = Modifier.padding(all = 4.dp),maxLines = if (isExpanded) Int.MAX_VALUE else 1,style = MaterialTheme.typography.bodyMedium)}}}
}
相关文章:

Android的Compose
Jetpack Compose 是用于构建原生 Android 界面的新工具包,无需修改任何 XML 布局,也不需要使用布局编辑器。相反,只需调用可组合函数来定义所需的元素,Compose 编译器即会完成后面的所有工作。 简而言之,使用Compose&…...

C++ STL->list模拟实现
theme: smartblue list list文档 list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素…...
基于python+django+vue.js开发的健身房管理系统
功能介绍 平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。 功能包括:教练管理、会员管理、场地管理、设备管理、用户管理、日志管理、系统信息模块。 源码地址 https://github.com/geeeeeeeek/python_…...

GPT-4对编程开发的支持
在编程开发领域,GPT-4凭借其强大的自然语言理解和代码生成能力,能够深刻理解开发者的意图,并基于这些需求提供精准的编程指导和解决方案。对于开发者来说,GPT-4能够在代码片段生成、算法思路设计、模块构建和原型实现等方面给予开…...

“成像光谱遥感技术中的AI革命:ChatGPT应用指南“
遥感技术主要通过卫星和飞机从远处观察和测量我们的环境,是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型,在理解和生成人类语言方面表现出了非凡的能力。本课程重点介绍ChatGPT在遥感中的应用,人工智…...
12.25 校招 实习 内推 面经
绿*泡*泡VX: neituijunsir 交流*裙 ,内推/实习/校招汇总表格 1、校招 | 百度2024校园招聘持续热招中 校招 | 百度2024校园招聘持续热招中 2、校招 | 毫末智行2024秋招补录进行时 校招 | 毫末智行2024秋招补录进行时 3、实习丨蔚来2024届冬季实习生计…...

深度学习基础之《TensorFlow框架(3)—TensorBoard》
一、TensorBoard可视化学习 1、TensorFlow有一个亮点就是,我们能看到自己写的程序的可视化效果,这个功能就是TensorBoard 2、TensorFlow可用于训练大规模深度神经网络所需的计算,使用该工具涉及的计算往往复杂而深奥。为了方便TensorFlow程…...

杨氏矩阵和杨辉三角
杨氏矩阵 有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。 要求:时间复杂度小于O(N); 分析 若要满足要求时间复杂度小于O(N),就不能每一行一个个…...

PostgreSQL教程(四):高级特性
一、简介 在之前的章节里我们已经涉及了使用SQL在PostgreSQL中存储和访问数据的基础知识。现在我们将要讨论SQL中一些更高级的特性,这些特性有助于简化管理和防止数据丢失或损坏。最后,我们还将介绍一些PostgreSQL扩展。 本章有时将引用教程࿰…...

168基于matlab的六自由度并联摇摆台的反解控制算法
基于matlab的六自由度并联摇摆台的反解控制算法,stewart平台,配有GUI界面,可以自定义角度,杆长等参数。设定动平台位姿即能得到电机参数。程序已调通,可直接运行。 168 六自由度并联摇摆台 反解控制算法 (xiaohongshu.…...
MDC 日志跟踪笔记
一、前言 本文主要解析应用中比较实在的一个log4j的链路应用,在经过一段时间的应用后发现还是很稳的,就记录一下这个MDC 代表Mapped Diagnostic Context(映射式诊断上下文)的情况。 Tisp: 它是一个线程安全的存放诊断日志的容器 T…...

MySQL错误-this is incompatible with sql_mode=only_full_group_by完美解决方案
项目场景 有时候,遇到数据库重复数据,需要将数据进行分组,并取出其中一条来展示,这时就需要用到group by语句。 但是,如果mysql是高版本,当执行group by时,select的字段不属于group by的字段的…...

人工智能|机器学习——基于机器学习的舌苔检测
代码下载: 基于深度学习的舌苔检测毕设留档.zip资源-CSDN文库 1 研究背景 1.1.研究背景与意义 目前随着人们生活水平的不断提高,对于中医主张的理念越来越认可,对中医的需求也越来越多。在诊断中,中医通过观察人的舌头的舌质、苔…...

SQL查询转化为 Elasticsearch 查询
使用SQL 转化为查询 Elasticsearch 支持 sql 语句转化为 elasticsearch 的 查询语句 第一步: 打开在线转换工具的网页,进入工具页面 第二步:在指定的输入框中输入需要转换的 sql 语句。 您学会了这么简单的办法...
目标检测教程视频指南大全
魔鬼面具-哔哩哔哩视频指南 必看干货系列(建议搞深度学习的小伙伴都看看,特别是图像相关) 深度学习常见实验问题与实验技巧(适用于所有模型,小白初学者必看!)还在迷茫深度学习中的改进实验应该从哪里开始改起的同学,一定要进来看看了!用自身…...

【Linux取经路】文件系统之重定向的实现原理
文章目录 一、再来理解重定向1.1 输出重定向效果演示1.2 重定向的原理1.3 dup21.4 输入重定向效果演示1.5 输入重定向代码实现 二、再来理解标准输出和标准错误2.1 同时对标准输出和标准错误进行重定向2.2 将标准输出和标准错误重定向到同一个文件 三、再看一切皆文件四、结语 …...

JAVA设计模式结构型模式
一、前言 java设计模式主要分为创建型模式,结构型模式和行为型模式。上一篇主要总结了行为型设计模式,本章总结,结构型模式。像创建型模式就不写了,比较简单。大概知道是工厂模式和建造者模式,原型模式就行࿰…...

第4讲引入JWT前后端交互
引入JWT前后端交互 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519); JWT就是一段字符串,用来进行用户身份认证的凭证,该字符串分成三段【头部、载荷、签证】 后端接口测试&…...
基于Java的车辆租赁管理平台/租车系统
功能介绍 平台采用B/S结构,后端采用主流的Springboot框架进行开发,前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 前台功能包括:首页、车辆详情、车辆预订、用户中心模块。后台功能包括:车辆管理、分类管理…...

如何升级至ChatGPT Plus:快速指南,ChatGPT的秘密武器GPT4.0是什么?
提到 ChatGPT。想必大家都有所耳闻。自从 2022 年上线以来,就受到国内外狂热的追捧和青睐,上线2个月,月活突破1个亿!!! 而且还在持续上涨中。因为有很多人都在使用 ChatGPT 。无论是各大头条、抖音等 App、…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...