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)}}}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据脱敏(五)脱敏算法-变换算法

脱敏算法篇使用阿里云数据脱敏算法为模板,使用算子平台快速搭建流程来展示数据 "变换脱敏"是一种数据处理技术&#xff0c;主要用于保护个人隐私和数据安全。它通过将敏感信息&#xff08;如姓名、身份证号、电话号码等&#xff09;进行某种形式的转换&#xff0c;使…

SpringBoot自动注入源码分析

Spring Boot何时注入Autowired标注的属性&#xff1f; 是在Bean实例化后&#xff0c;填充Bean的时候注入Autowired标注的属性 如果注入类型的Bean存在多个&#xff0c;Spring Boot是如何处理的&#xff1f; 如果存在多个类型的Bean&#xff0c;会根据primary—>javax.ann…

Redis典型应用之分布式锁

目录 前言 分布式锁的基础实现 引入过期时间&#xff1a; 引入校验ID&#xff1a; 引入lua lua的简介&#xff1a; 引入看门狗 &#xff08;watch dog&#xff09; 引入Redlock算法 前言 在一个分布式系统中&#xff0c;也会涉及到多个节点同时去访问一个公共资源的时候&am…

ArcGIS API for JavaScript 4.X 本地部署(js,字体)

0 目录&#xff08;4.19&#xff09; /4.19/ 1 修改文件 1.1 init.js 编辑器打开/4.19/init.js搜索文本[HOSTNAME_AND_PATH_TO_JSAPI]&#xff0c;然后将其连同前面的https://替换为http://ip地址/4.19&#xff0c;可以是localhost&#xff0c;只能本机引用 替换后&#xff…

Selenium 自动化测试—如何搭建自动化测试环境

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 最近也有很多人私下问我&#xff0c;selenium学习难吗&#xff0c;基础入门的学习内容很多是3以前…

【linux】体系结构和os管理

冯诺依曼体系结构 输入单元&#xff1a;包括键盘, 鼠标&#xff0c;扫描仪, 写板等 中央处理器(CPU)&#xff1a;含有运算器和控制器等 输出单元&#xff1a;显示器&#xff0c;打印机等 这里的存储器指的是内存 三者是相互连接的&#xff0c;设备之间会进行数据的来回拷贝&am…

社区店经营全攻略:如何选址、运营并打造火爆生意?

随着电商的兴起&#xff0c;实体店的经营面临着越来越多的挑战。然而&#xff0c;社区店依然具有独特的优势&#xff0c;如便捷的地理位置、与消费者的紧密互动等。 作为在社区店开鲜奶吧5年的创业者&#xff0c;我深有感触&#xff0c;那么这篇文章将为你提供最有价值的干货信…

计算机设计大赛 深度学习人体跌倒检测 -yolo 机器视觉 opencv python

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的人体跌倒检测算法研究与实现 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满…

深入浅出JVM(一)之Hotspot虚拟机中的对象

本篇文章思维导图 对象的创建 对象的创建可以分为五个步骤:检查类加载,分配内存,初始化零值,设置对象头,执行实例构造器 类加载检查 HotSpot虚拟机遇到一条new指令,会先检查能否在常量池中定位到这个类的符号引用,检查这个类是否类加载过 没有类加载过就去类加载类加载过就进…

基于Java+SpringBoot的旅游路线规划系统(源码+论文)

文章目录 目录 文章目录 前言 一、功能设计 二、功能实现 1.1 前端首页模块的实现 1.2 景点新闻 1.3 景点在线预订 1.4 酒店在线预订 1.5 管理员景点管理 1.6 管理员旅游线路管理 1.7 酒店信息管理 三、库表设计 前言 随着我国的经济的不断发展&#xff0c;现在的一些热门的景…

【C++】类与对象(构造函数、析构函数、拷贝构造函数、常引用)

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;http://t.csdnimg.cn/eCa5z 目录 类的6个默认成员函数 构造函数 特性 析构函数 特性 析构的顺序 拷贝构造函数 特性 常引用 前言 &…

HBase 进阶

参考来源: B站尚硅谷HBase2.x 目录 Master 架构RegionServer 架构写流程MemStore Flush读流程HFile 结构读流程合并读取数据优化 StoreFile CompactionRegion Split预分区&#xff08;自定义分区&#xff09;系统拆分 Master 架构 Master详细架构 1&#xff09;Meta 表格介…