添加可滚动的列表

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(下载 ZIP)按钮将项目保存到您的计算机上。等待下载完成。
  2. 在您的计算机上找到该文件(很可能位于 Downloads 文件夹中)。
  3. 双击该 ZIP 文件以解压缩。这将创建一个包含项目文件的新文件夹。

在 Android Studio 中打开项目

  1. 启动 Android Studio。
  2. Welcome to Android Studio(欢迎使用 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 软件包将包含由数据类表示的数据模型。该数据类将由属性组成,这些属性表示与“Affirmation”相关的信息,其中包含字符串资源和图片资源。软件包是包含类甚至其他目录的目录。

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. stringResourceId 属性添加 @StringRes 注解,并为 imageResourceId 添加 @DrawableRes 注解。stringResourceId 表示存储在字符串资源中的肯定语文本的 ID。imageResourceId 表示存储在 Drawable 资源中的肯定语图片的 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 是在一个容器中显示内容和操作的界面。Affirmation 卡片将如下图所示

95111184aed54fa3.png

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

  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.dpelevation 属性稍后会详细介绍。

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 方法将加载矢量 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)
      )
    }
  }
}
  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 参数,传递一个 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,您为创建它付出了艰辛的努力!为了检查卡片是否正确,您可以创建一个可以在不启动整个应用的情况下预览的可组合项。

  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(下载 ZIP)按钮将项目保存到您的计算机上。等待下载完成。
  2. 在您的计算机上找到该文件(很可能位于 Downloads 文件夹中)。
  3. 双击该 ZIP 文件以解压缩。这将创建一个包含项目文件的新文件夹。

在 Android Studio 中打开项目

  1. 启动 Android Studio。
  2. Welcome to Android Studio(欢迎使用 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 可组合项创建可滚动的列表。
  • 使用自定义列表项构建列表。