添加可滚动列表

1. 准备工作

在此 Codelab 中,您将学习如何使用 Jetpack Compose 在应用中创建可滚动列表。

您将使用 Affirmations 应用,该应用会显示配有精美图片的自我肯定话语列表,为您的日常生活带来满满正能量!

数据已经有了,您只需获取数据并将其显示在界面中即可。

前提条件

  • 熟悉 Kotlin 中的列表
  • 拥有使用 Jetpack Compose 构建布局的经验
  • 拥有在设备或模拟器上运行应用的经验

学习内容

  • 如何使用 Jetpack Compose 创建 Material Design 卡片?
  • 如何使用 Jetpack Compose 创建可滚动列表?

构建内容

  • 您将使用一个现有应用,在其界面中添加可滚动列表

完成后的效果将如下所示:

f6f09800b74f4700.png

所需条件

  • 一台连接到互联网并安装了网络浏览器和 Android Studio 的计算机
  • 能够访问 GitHub

下载起始代码

在 Android Studio 中,打开 basic-android-kotlin-compose-training-affirmations 文件夹。

  1. 进入为此项目提供的 GitHub 代码库页面。
  2. 验证分支名称是否与此 Codelab 中指定的分支名称一致。例如,在以下屏幕截图中,分支名称为 main

1e4c0d2c081a8fd2.png

  1. 在项目的 GitHub 页面上,点击 Code 按钮,以打开一个弹出式窗口。

1debcf330fd04c7b.png

  1. 在弹出式窗口中,点击 Download ZIP 按钮,将项目保存到计算机上。等待下载完成。
  2. 在计算机上找到该文件(很可能在 Downloads 文件夹中)。
  3. 双击 ZIP 文件进行解压缩。系统将创建一个包含项目文件的新文件夹。

在 Android Studio 中打开项目

  1. 启动 Android Studio。
  2. Welcome to Android Studio 窗口中,点击 Open

d8e9dbdeafe9038a.png

注意:如果 Android Studio 已经打开,则改为依次选择 File > Open 菜单选项。

8d1fda7396afe8e5.png

  1. 在文件浏览器中,前往解压缩的项目文件夹所在的位置(很可能在 Downloads 文件夹中)。
  2. 双击该项目文件夹。
  3. 等待 Android Studio 打开项目。
  4. 点击 Run 按钮 8de56cba7583251f.png 以构建并运行应用。请确保该应用按预期构建。

2. 创建列表项数据类

为 Affirmation 创建数据类

在 Android 应用中,列表由列表项组成。如果包含单项数据,列表项可以是字符串或整数等简单内容。对于包含多项数据的列表项(例如图片和文本),您需要一个包含所有这些属性的类。数据类是一种仅包含属性的类,可以提供一些可与这些属性配合使用的实用程序方法。

  1. com.example.affirmations 下创建一个新的软件包。4a51cb670bbec405.png

将新软件包命名为 model。“model”软件包会包含将由一个数据类表示的数据模型。该数据类由表示“自我肯定话语”内容相关信息的属性组成;“自我肯定话语”将包含字符串资源和图片资源。软件包是包含类以及其他目录的目录。

9ea1f8880ca90ea0.png

  1. com.example.affirmations.model 软件包中创建一个新类。a9515a8b47715a22.png

将新类命名为 Affirmation,并将其设为 Data Class

b36be7f428fd1672.png

  1. 每个 Affirmation 均包含一张图片和一个字符串。在 Affirmation 数据类中创建两个 val 属性,将其中一个属性命名为 stringResourceId,另一个命名为 imageResourceId。这两个属性的值都应为整数。

Affirmation.kt

data class Affirmation(
   val stringResourceId: Int,
   val imageResourceId: Int
)
  1. 使用 @StringRes 注解标记 stringResourceId 属性,并使用 @DrawableRes 注解标记 imageResourceId 属性。stringResourceId 表示存储在字符串资源中的自我肯定话语文本的 ID。imageResourceId 表示存储在可绘制资源中的自我肯定话语图片的 ID。

Affirmation.kt

data class Affirmation(
   @StringRes val stringResourceId: Int,
   @DrawableRes val imageResourceId: Int
)
  1. 现在,打开 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 是一种在单个容器中显示内容和操作的 Surface。自我肯定话语卡片如下所示:

95111184aed54fa3.png

该卡片会显示一张图片并在其下方显示一些文本。这种垂直布局可以使用封装在 Card 可组合项中的 Column 可组合项来实现。您可以自己尝试创建该布局,也可以按照以下步骤操作来实现它。

  1. 打开 MainActivity.kt 文件。

1e348baaf91552f4.png

  1. AffirmationApp() 方法下创建一个名为 AffirmationCard() 的新方法,并使用 @Composable 注解对其进行注解。

MainActivity.kt

@Composable
fun AffirmationApp() {
   val context = LocalContext.current
   AffirmationsTheme {

   }
}

@Composable
fun AffirmationCard() {

}
  1. 修改方法签名,以接受 Affirmation 对象作为形参。Affirmation 对象来自 model 软件包。

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation) {

}
  1. 向签名添加 modifier 参数。将该参数的默认值设置为 Modifier

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {

}
  1. AffirmationCard 方法内,调用 Card 可组合项。传入以下参数:modifierelevation。传递一个 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) {
  }
}
  1. Card 可组合项内添加一个 Column 可组合项。Column 可组合项中包含的项会自行在界面中垂直排列。这样一来,您就可以在相关文本上方放置图片。相反,Row 可组合项会以水平方式排列其包含的项。

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
    Column {
    }
  }
}
  1. Column 可组合项的 lambda 正文内添加 Image 可组合项。之前提到,Image 可组合项始终需要一项用于显示的资源和一个 contentDescription。该资源应该是传递给 painter 参数的 painterResourcepainterResource 方法会加载矢量可绘制对象或光栅化资源格式(例如 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)
      )
    }
  }
}
  1. 除了 paintercontentDescription 参数之外,还应传递 modifiercontentScalecontentScale 用于决定图片应如何缩放和显示。Modifier 对象应设置 fillMaxWidth 属性,并将高度设置为 194.dpcontentScale 应为 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
      )
    }
  }
}
  1. Column 内,在 Image 可组合项之后创建一个 Text 可组合项。将 affirmation.stringResourceIdstringResource 传递给 text 形参,传递 padding 属性已设置为 16.dpModifier 对象,并通过将 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 应用界面的核心,通过您的辛勤努力,它已经创建好了!如要检查卡片能否正确显示,您可以创建一个无需启动整个应用即可预览的可组合项。

  1. 创建一个名为 AffirmationCardPreview() 的私有方法。使用 @Preview@Composable 为该方法添加注解。

MainActivity.kt

@Preview
@Composable
private fun AffirmationCardPreview() {
}
  1. 在该方法内,调用 AffirmationCard 可组合项,并向其传递一个新的 Affirmation 对象(R.string.affirmation1 字符串资源和 R.drawable.image1 可绘制资源已传递到该对象的构造函数中)。

MainActivity.kt

@Preview
@Composable
private fun AffirmationCardPreview() {
  AffirmationCard(Affirmation(R.string.affirmation1, R.drawable.image1))
}
  1. 打开 Split 标签页,您将看到 AffirmationCard 的预览。如有必要,请点击 Design 窗格中的 Build & Refresh,使系统显示预览。84904da4a33413ce.png

创建列表

列表项组件是列表的构建块。创建列表项后,您可以利用它来创建列表组件。

  1. 创建一个名为 AffirmationList() 的方法,使用 @Composable 注解对其进行注解,并在方法签名中将 Affirmation 对象的 List 声明为形参。

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>) {
}
  1. 在方法签名中将 modifier 对象声明为形参,并将默认值设为 Modifier

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
}
  1. 在 Jetpack Compose 中,可以使用 LazyColumn 可组合项创建可滚动列表。LazyColumnColumn 之间的区别在于,当要显示的项数量较少时,应使用 Column,因为 Compose 会一次性加载所有项。Column 只能保存预定义或固定数量的可组合项。LazyColumn 可以按需添加内容,因此非常适合较长的列表,尤其是当列表长度未知时。LazyColumn 还提供默认滚动行为,无需添加其他代码。在 AffirmationList() 方法内声明一个 LazyColumn 可组合项。

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
  }
}
  1. LazyColumn 的 lambda 正文中,调用 items() 方法并传入 affirmationListitems() 方法用于向 LazyColumn 添加项。此方法对该可组合项有些许独特,对于大多数可组合项来说并不常见。

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){
    }
  }
}
  1. 调用 items() 方法需要 lambda 函数。在该函数中,指定一个 affirmation 形参,用于表示 affirmationList 中的一个自我肯定话语项。

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){ affirmation ->
    }
  }
}
  1. 针对列表中的每个自我肯定话语,调用 AffirmationCard() 可组合项并向其传递 affirmation

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){ affirmation ->
      AffirmationCard(affirmation)
    }
  }
}

显示列表

  1. 在 lambda 中,调用 AffirmationList 可组合项,并将 DataSource().loadAffirmations() 传递给 affirmationList 参数。

MainActivity.kt

@Composable
fun AffirmationApp() {
   AffirmationsTheme {
       Scaffold(
           content = {
               AffirmationList(affirmationList = Datasource().loadAffirmations())
           }
       )
   }
}

在设备或模拟器上运行 Affirmations 应用,并查看最终效果!

f6f09800b74f4700.png

4. 获取解决方案代码

如果您想查看解决方案代码,请前往 GitHub 查看。

  1. 进入为此项目提供的 GitHub 代码库页面。
  2. 验证分支名称是否与此 Codelab 中指定的分支名称一致。例如,在以下屏幕截图中,分支名称为 main

1e4c0d2c081a8fd2.png

  1. 在项目的 GitHub 页面上,点击 Code 按钮,以打开一个弹出式窗口。

1debcf330fd04c7b.png

  1. 在弹出式窗口中,点击 Download ZIP 按钮,将项目保存到计算机上。等待下载完成。
  2. 在计算机上找到该文件(很可能在 Downloads 文件夹中)。
  3. 双击 ZIP 文件进行解压缩。系统将创建一个包含项目文件的新文件夹。

在 Android Studio 中打开项目

  1. 启动 Android Studio。
  2. Welcome to Android Studio 窗口中,点击 Open

d8e9dbdeafe9038a.png

注意:如果 Android Studio 已经打开,则改为依次选择 File > Open 菜单选项。

8d1fda7396afe8e5.png

  1. 在文件浏览器中,前往解压缩的项目文件夹所在的位置(很可能在 Downloads 文件夹中)。
  2. 双击该项目文件夹。
  3. 等待 Android Studio 打开项目。
  4. 点击 Run 按钮 8de56cba7583251f.png 以构建并运行应用。请确保该应用按预期构建。

5. 总结

现在,您已了解如何使用 Jetpack Compose 创建卡片、列表项和可滚动列表!请注意,这些只是用于创建列表的基本工具。您可以尽情挥洒创意,按自己的喜好自定义列表项!

总结

  • 使用 Card 可组合项创建列表项。
  • 修改 Card 可组合项中包含的界面。
  • 使用 LazyColumn 可组合项创建可滚动列表。
  • 使用自定义列表项构建列表。