Android Jetpack Compose入门教程(二)

news2025/2/26 2:55:40

一、列表和动画

列表和动画在应用内随处可见。在本课中,您将学习如何利用 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
        //variable
        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.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 line
                    maxLines = 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
        //variable
        var 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 line
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

在这里插入图片描述
在这里插入图片描述

二、后续步骤

恭喜,您已完成 Compose 教程!您已高效地构建了一个简单的聊天界面,该界面显示包含图片和文字的可展开动画消息列表,使用 Material Design 原则设计,添加了深色主题且具有预览功能,所有内容只需不到 100 行代码!

以下是您目前为止所学的内容:

  • 定义可组合函数
  • 在可组合项中添加不同的元素
  • 使用布局可组合项构建界面组件
  • 使用修饰符扩展可组合项
  • 创建高效列表
  • 跟踪状态以及修改状态
  • 在可组合项上添加用户互动
  • 在展开消息时显示动画效果

Compose官方中文课程

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

openh264 帧内预测编码过程源码分析

函数关系 说明&#xff1a; 可以看到完成帧内预测编码的核心函数就是 WelsMdI16x16、WelsMdI4x4、WelsMdI4x4Fast 、WelsMdIntraChroma 四个函数。 原理 WelsMdI16x16函数 功能&#xff1a;针对16x16像素块的帧内模式决策过程&#xff1a; 局部变量申明&#xff1b;根据宏块…

python如何终止程序运行

方法1&#xff1a;采用sys.exit(0)&#xff0c;正常终止程序&#xff0c;从图中可以看到&#xff0c;程序终止后shell运行不受影响。 方法2&#xff1a;采用os._exit(0)关闭整个shell&#xff0c;从图中看到&#xff0c;调用sys._exit(0)后整个shell都重启了&#xff08;RESTAR…

卡塔尔.巴林:海外媒体投放-宣发.发稿效果显著提高

引言 卡塔尔和巴林两国积极采取措施&#xff0c;通过海外媒体投放和宣发&#xff0c;将本国的商业新闻和相关信息传达给更广泛的受众。在这一过程中&#xff0c;卡塔尔新闻网、巴林商业新闻和摩纳哥新闻网等媒体起到了关键作用。通过投放新闻稿&#xff0c;这些国际化的媒体平…

UITableView之显示单组数据Demo

需求 UITableView实现显示单组数据。尝试设置不同行高度不同。 效果&#xff1a; 数据展示 实现 与之前分组显示数据的区别在于懒加载的数据模型不同。 &#xff08;1&#xff09;声明数据模型类 类的属性一定要和plist中数据的字段保持一致 interface CZhero : NSObject /…

idea在空工程中添加新模块并测试的步骤

ServicesTest是空的工程&#xff0c;没有pom文件。现在需要在ServicesTest目录下添加新模块作为新的工程&#xff0c;目的是写一下别的技术功能。 原先目录结构&#xff0c;ServicesTest是空的工程&#xff0c;没有pom文件。下面的几个模块是新的工程&#xff0c;相互独立。 1.…

数栈xAI:轻量化、专业化、模块化,四大功能革新 SQL 开发体验

在这个数据如潮的时代&#xff0c;SQL 已远远超越了简单的查询语言范畴&#xff0c;它已成为数据分析和决策制定的基石&#xff0c;成为撬动企业智慧决策的关键杠杆。SQL 的编写和执行效率直接关系到数据处理的速度和分析结果的深度&#xff0c;对企业洞察市场动态、优化业务流…

谁说Python GUI难?用pywebview打造现代化GUI界面

在Python的世界里&#xff0c;我们经常需要为程序添加一个图形用户界面&#xff08;GUI&#xff09;。传统上&#xff0c;Tkinter、PyQt或Kivy等库是常用的选择。但是&#xff0c;今天我们要介绍的是一个更简单、更现代的方法——pywebview。它让你可以使用HTML、CSS和JavaScri…

OpenCV查找图像中的轮廓并且展示

1、查找轮廓随机用不同的颜色画出 import cv2 import numpy as npdef get_contour_colors(num_contours):# 定义颜色表 (BGR 格式)colors [(255, 0, 0),(255, 50, 0),(255, 100, 0),(255, 150, 0),(255, 200, 0),(255, 255, 0),(200, 255, 0),(150, 255, 0),(100, 255, 0),(5…

2.6数据报与虚电路

数据报 当作为通信子网用户的端系统要发送一个报文时&#xff0c;在端系统中实现的高层协议先把报文拆成若干个带有序号的数据单元&#xff0c;并在网络层加上地址等控制信息后形成数据报分组(即网络层PDU)中间结点存储分组一段很短的时间&#xff0c;找到最佳的路由后&#x…

【StructueEngineering】Wind Load Combination Patterns风荷载组合模式

文章目录 Combination PatternsBasic Rules of Combinations组合的基本规律Specific Combination Patterns1. First 8 Combinations (1 to 8)2. Middle 8 Combinations (9 to 16)3. Last 8 Combinations (17 to 24) Summary of CombinationsKey Variables and Parameters with …

Base64编码方式的介绍及其编码解码

一、Base64是什么 Base64是一种用于将二进制数据编码为ASCII字符的编码方式&#xff0c;主要目的是为了能够在文本环境中传输和存储二进制数据。这种编码方式广泛应用于电子邮件、HTTP协议和其他需要传输或存储二进制数据的地方。 二、发明Base64编码的原因 Base64编码的发明解…

《转载》前苏联的三进制计算机Setun

1、苏联的三进制计算机概述 早在 1956 年&#xff0c;就需要创建一种可在大学和实验室中使用的实用数字计算机模型。为此&#xff0c;需要一种易于学习、可靠、廉价但同时高效、专为大规模使用而设计的小型计算机。 对这种机器的要求&#xff1a;运行速度必须等于每秒数百次操作…

破解发展难题 台山这家合作社以农业社会化服务助推乡村振兴

风吹稻田千层浪&#xff0c;眼下&#xff0c;台山四九镇的早稻长势喜人&#xff0c;沉甸甸的稻穗迎风而动&#xff0c;已进入破口抽穗的关键期&#xff0c;即将在6月底陆续迎来丰收。在台山市明华汇种养专业合作社管理的稻田里&#xff0c;合作社负责人梁明喜正仔细观察着稻苗的…

(代数:解一元二次方程)可以使用下面的公式求一元二次方程 ax2+bx+c0 的两个根:

(代数:解一元二次方程)可以使用下面的公式求一元二次方程 ax2bxc0 的两个根: b2-4ac 称作一元二次方程的判别式。如果它是正值,那么一元二次方程就有两个实数根。 如果它为 0&#xff0c;方程式就只有一个根。如果它是负值&#xff0c;方程式无实根。 编写程序&#xff0c;提示…

单点登录分析介绍

文章目录 1、单点登录解决方案1.1、后端保存登录状态1.2、token模式 2、user服务-登录接口2.1、UserController2.2、UserInfoServiceImpl2.3、载荷2.4、响应2.5、Redis Desktop Manager 1、单点登录解决方案 多个系统只有一个登录服务 1.1、后端保存登录状态 1.2、token模式 …

WordPress、Typecho 站点如何让 CloudFlare 缓存加速

众所周知 WordPress、Typecho 都是著名动态博客站点(一个最简单的判断依据就是都要依赖结合数据库),这类站点在 CDN 缓存上都有一个致命的缓存弊端就是动静态请求的区分,理论上要让 CDN 绕过所有的动态请求,缓存所有的静态请求,否则就会造成前端登录和非登录状态的混乱,…

聊聊分布式集群的基本概念

在当前主流的分布式架构中&#xff0c;各种各样的集群技术几乎成了任何想要提升系统稳定性和处理能力的团队的必备技能。虽然各种中间件和系统都有让人看似眼花缭乱的集群实现方案&#xff0c;但其背后仍然逃不过一些核心的技术概念&#xff0c;我会结合几个我比较熟悉的中间件…

java.nio.charset.UnmappableCharacterException

问题 java.lang.IllegalArgumentException: java.nio.charset.UnmappableCharacterException: Input length 1 解释为编码转换有问题 问题错在位置 非汉字存在 打包的时候就会报异常

怎么把wma格式转化为mp3格式?四种wma格式转成MP3格式的方法

怎么把wma格式转化为mp3格式&#xff1f;转换WMA格式音频文件为MP3格式是一个常见的需求&#xff0c;尤其是在我们希望在不同设备或平台上播放音频时。WMA格式虽然在Windows系统中较为常见&#xff0c;但在其他平台上的兼容性可能不如MP3格式。因此&#xff0c;将WMA转换为MP3是…

c#引用dll报错cs8370功能“本地函数特性“在c#7.3中不可用

cs8370:功能"本地函数特性"在c#7.3中不可用 解决方法&#xff1a; 代码放在form类里面