1. 开始之前
在此 Codelab 中,您将学习如何使用 Jetpack Compose 在应用中创建可滚动的列表。
您将使用 Affirmations 应用,该应用会显示一张肯定语列表,其中包含精美图片,为您的生活带来积极影响!
数据已准备就绪,您只需将数据提取出来并在界面中显示。
前提条件
- 熟悉 Kotlin 中的列表
- 具备使用 Jetpack Compose 构建布局的经验
- 具备在设备或模拟器上运行应用的经验
您将学到什么
- 如何使用 Jetpack Compose 创建 Material Design 卡片
- 如何使用 Jetpack Compose 创建可滚动的列表
您将构建什么
- 您将使用现有应用,并为界面添加一个可滚动的列表
成品将如下图所示

您需要准备什么
- 一台联网的计算机、网络浏览器和 Android Studio
- 可访问 GitHub
下载起始代码
在 Android Studio 中,打开 basic-android-kotlin-compose-training-affirmations 文件夹。
- 导航到该项目的指定 GitHub 代码库页面。
- 验证分支名称与 Codelab 中指定的分支名称一致。例如,在以下屏幕截图中,分支名称为 main。

- 在该项目的 GitHub 页面上,点击 Code(代码)按钮,此时会弹出一个窗口。

- 在弹出的窗口中,点击 Download ZIP(下载 ZIP)按钮将项目保存到您的计算机上。等待下载完成。
- 在您的计算机上找到该文件(很可能位于 Downloads 文件夹中)。
- 双击该 ZIP 文件以解压缩。这将创建一个包含项目文件的新文件夹。
在 Android Studio 中打开项目
- 启动 Android Studio。
- 在 Welcome to Android Studio(欢迎使用 Android Studio)窗口中,点击 Open(打开)。

注意:如果 Android Studio 已打开,则选择 File(文件)> Open(打开)菜单选项。

- 在文件浏览器中,导航到解压缩后的项目文件夹所在的位置(很可能位于您的 Downloads 文件夹中)。
- 双击该项目文件夹。
- 等待 Android Studio 打开项目。
- 点击 Run(运行)按钮
构建并运行应用。确保应用按预期构建。
2. 创建列表项数据类
为 Affirmation 创建数据类
在 Android 应用中,列表由列表项组成。对于单一的数据段,可以是很简单的字符串或整数。对于具有多个数据段(例如图片和文本)的列表项,您需要一个包含所有这些属性的类。数据类是一种仅包含属性的类,可以提供一些用于处理这些属性的实用方法。
- 在 com.example.affirmations 下创建一个新软件包。

将新软件包命名为 model。model 软件包将包含由数据类表示的数据模型。该数据类将由属性组成,这些属性表示与“Affirmation”相关的信息,其中包含字符串资源和图片资源。软件包是包含类甚至其他目录的目录。

- 在 com.example.affirmations.model 软件包中创建一个新类。

将新类命名为 Affirmation 并使其成为 Data Class。

- 每个
Affirmation都包含一张图片和一个字符串。在Affirmation数据类中创建两个val属性。一个应命名为stringResourceId,另一个应命名为imageResourceId。它们都应是整数。
Affirmation.kt
data class Affirmation(
val stringResourceId: Int,
val imageResourceId: Int
)
- 为
stringResourceId属性添加@StringRes注解,并为imageResourceId添加@DrawableRes注解。stringResourceId表示存储在字符串资源中的肯定语文本的 ID。imageResourceId表示存储在 Drawable 资源中的肯定语图片的 ID。
Affirmation.kt
data class Affirmation(
@StringRes val stringResourceId: Int,
@DrawableRes val imageResourceId: Int
)
- 现在,打开 com.example.affirmations.data 软件包中的
Datasource.kt文件,并取消注释Datasource类中的内容。
Datasource.kt
class Datasource() {
fun loadAffirmations(): List<Affirmation> {
return listOf<Affirmation>(
Affirmation(R.string.affirmation1, R.drawable.image1),
Affirmation(R.string.affirmation2, R.drawable.image2),
Affirmation(R.string.affirmation3, R.drawable.image3),
Affirmation(R.string.affirmation4, R.drawable.image4),
Affirmation(R.string.affirmation5, R.drawable.image5),
Affirmation(R.string.affirmation6, R.drawable.image6),
Affirmation(R.string.affirmation7, R.drawable.image7),
Affirmation(R.string.affirmation8, R.drawable.image8),
Affirmation(R.string.affirmation9, R.drawable.image9),
Affirmation(R.string.affirmation10, R.drawable.image10))
}
}
3. 将列表添加到应用中
创建列表项卡片
此应用旨在显示肯定语列表。配置界面以显示列表的第一步是创建列表项。每个肯定语项包含一张图片和一个字符串。这些项目的数据随起始代码一同提供,您将创建用于显示此类项目的界面组件。
该项将由一个 Card 可组合项组成,其中包含一个 Image 和一个 Text 可组合项。在 Compose 中,Card 是在一个容器中显示内容和操作的界面。Affirmation 卡片将如下图所示

卡片显示了一张图片,图片下方有一些文字。这种垂直布局可以通过将 Column 可组合项封装在 Card 可组合项中来实现。您可以自行尝试,也可以按照以下步骤来实现。
- 打开 MainActivity.kt 文件。

- 在
AffirmationApp()方法下方创建一个新方法,名为AffirmationCard(),并为其添加@Composable注解。
MainActivity.kt
@Composable
fun AffirmationApp() {
val context = LocalContext.current
AffirmationsTheme {
}
}
@Composable
fun AffirmationCard() {
}
- 修改方法签名,使其将
Affirmation对象作为参数。此Affirmation对象来自model软件包。
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation) {
}
- 向签名中添加
modifier参数。为该参数设置Modifier的默认值。
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
}
- 在
AffirmationCard方法内,调用Card可组合项。传入以下参数:modifier和elevation。为modifier参数传递一个Modifier对象,其padding属性设置为8.dp。为elevation传递一个值4.dp。elevation属性稍后会详细介绍。
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
}
}
- 在
Card可组合项内添加一个Column可组合项。Column可组合项内的项在界面中垂直排列。这允许您将图片放在关联文本上方。相反,Row可组合项会将其包含的项水平排列。
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
Column {
}
}
}
- 在
Column可组合项的 lambda 主体中添加一个Image可组合项。请记住,Image可组合项始终需要一个要显示的资源和contentDescription。资源应是传递给painter参数的painterResource。painterResource方法将加载矢量 Drawable 或光栅化素材格式(例如 PNG)。此外,为contentDescription参数传递一个stringResource。
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId)
)
}
}
}
- 除了
painter和contentDescription参数外,还要传递modifier和contentScale。contentScale确定图片的缩放和显示方式。Modifier对象应设置fillMaxWidth属性,高度为194.dp。contentScale应为ContentScale.Crop。
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId),
modifier = Modifier
.fillMaxWidth()
.height(194.dp),
contentScale = ContentScale.Crop
)
}
}
}
- 在
Column内,在Image可组合项之后创建一个Text可组合项。将affirmation.stringResourceId的stringResource传递给text参数,传递一个Modifier对象,其padding属性设置为16.dp,并通过将MaterialTheme.typography.h6传递给style参数来设置文本主题。
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId),
modifier = Modifier
.fillMaxWidth()
.height(194.dp),
contentScale = ContentScale.Crop
)
Text(
text = stringResource(affirmation.stringResourceId),
modifier = Modifier.padding(16.dp),
style = MaterialTheme.typography.h6
)
}
}
}
预览 AffirmationCard 可组合项
卡片是 Affirmations 应用界面核心的 UI,您为创建它付出了艰辛的努力!为了检查卡片是否正确,您可以创建一个可以在不启动整个应用的情况下预览的可组合项。
- 创建一个名为
AffirmationCardPreview()的私有方法。使用@Preview和@Composable注解该方法。
MainActivity.kt
@Preview
@Composable
private fun AffirmationCardPreview() {
}
- 在该方法内部,调用
AffirmationCard可组合项,并向其传递一个新的Affirmation对象,将R.string.affirmation1字符串资源和R.drawable.image1可绘制资源传递到其构造函数中。
MainActivity.kt
@Preview
@Composable
private fun AffirmationCardPreview() {
AffirmationCard(Affirmation(R.string.affirmation1, R.drawable.image1))
}
- 打开 Split 标签页,您将看到
AffirmationCard的预览。如有必要,点击 Design 窗格中的 Build & Refresh(构建并刷新)以显示预览。
创建列表
列表项组件是列表的构建块。创建列表项后,您可以利用它来构建列表组件本身。
- 创建一个名为
AffirmationList()的方法,为其添加@Composable注解,并在方法签名中声明一个Affirmation对象List作为参数。
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>) {
}
- 在方法签名中声明一个
modifier对象作为参数,默认值为Modifier。
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
}
- 在 Jetpack Compose 中,可以使用
LazyColumn可组合项创建可滚动的列表。LazyColumn和Column的区别在于,当您要显示的项很少时,应使用Column,因为 Compose 会一次性加载所有项。Column只能容纳预定义或固定数量的可组合项。LazyColumn可以按需添加内容,因此非常适合用于长列表,特别是当列表长度未知时。LazyColumn还默认提供滚动功能,无需额外代码。在AffirmationList()方法内声明一个LazyColumn可组合项。
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn {
}
}
- 在
LazyColumn的 lambda 主体中,调用items()方法,并传入affirmationList。items()方法是向LazyColumn添加项的方式。此方法对此可组合项来说有些独特,对于大多数可组合项而言,这并非通用做法。
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn {
items(affirmationList){
}
}
}
- 调用
items()方法需要一个 lambda 函数。在该函数中,指定一个参数affirmation,它表示affirmationList中的一个肯定语项。
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn {
items(affirmationList){ affirmation ->
}
}
}
- 对于列表中的每个肯定语,调用
AffirmationCard()可组合项,并向其传递affirmation。
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn {
items(affirmationList){ affirmation ->
AffirmationCard(affirmation)
}
}
}
显示列表
- 在 lambda 中,调用
AffirmationList可组合项,并将DataSource().loadAffirmations()传递给affirmationList参数。
MainActivity.kt
@Composable
fun AffirmationApp() {
AffirmationsTheme {
Scaffold(
content = {
AffirmationList(affirmationList = Datasource().loadAffirmations())
}
)
}
}
在设备或模拟器上运行 Affirmations 应用,查看成品!

4. 获取解决方案代码
如果您想查看解决方案代码,请在 GitHub 上查看。
- 导航到该项目的指定 GitHub 代码库页面。
- 验证分支名称与 Codelab 中指定的分支名称一致。例如,在以下屏幕截图中,分支名称为 main。

- 在该项目的 GitHub 页面上,点击 Code(代码)按钮,此时会弹出一个窗口。

- 在弹出的窗口中,点击 Download ZIP(下载 ZIP)按钮将项目保存到您的计算机上。等待下载完成。
- 在您的计算机上找到该文件(很可能位于 Downloads 文件夹中)。
- 双击该 ZIP 文件以解压缩。这将创建一个包含项目文件的新文件夹。
在 Android Studio 中打开项目
- 启动 Android Studio。
- 在 Welcome to Android Studio(欢迎使用 Android Studio)窗口中,点击 Open(打开)。

注意:如果 Android Studio 已打开,则选择 File(文件)> Open(打开)菜单选项。

- 在文件浏览器中,导航到解压缩后的项目文件夹所在的位置(很可能位于您的 Downloads 文件夹中)。
- 双击该项目文件夹。
- 等待 Android Studio 打开项目。
- 点击 Run(运行)按钮
构建并运行应用。确保应用按预期构建。
5. 总结
您现在知道如何使用 Jetpack Compose 创建卡片、列表项和可滚动列表了!请记住,这些只是创建列表的基本工具。您可以尽情发挥创意,按照您的喜好自定义列表项!
摘要
- 使用
Card可组合项创建列表项。 - 修改
Card可组合项中包含的界面。 - 使用
LazyColumn可组合项创建可滚动的列表。 - 使用自定义列表项构建列表。