使用卡片显示一组图片

1. 准备工作

在上一个 Codelab 中,您创建了 Affirmations 应用,该应用会在 RecyclerView 中显示文本列表。

7ac81c2a9a79365b.png

在此后续 Codelab 中,您将向应用中的每句自我肯定话语添加一张励志图片。您将使用 Material Components for Android 库中的 MaterialCardView 微件,在卡片中显示每句自我肯定话语的文本和图片。然后,您将美化界面,让用户看到的界面图文更统一且更精美,这样就完成了应用。完成后的应用屏幕截图如下:

8d7a20a5d7a079ce.png

前提条件

  • 可以向应用添加图片资源。
  • 可以熟练修改 XML 布局。
  • 能够创建一个在 RecyclerView 中显示文本列表的应用。
  • 能够为 RecyclerView 创建适配器。

学习内容

  • 如何向 RecyclerView 中显示的自我肯定话语列表添加图片。
  • 如何在 RecyclerView 项布局中使用 MaterialCardView
  • 如何在界面中更改视觉效果,使应用看起来更精美。

构建内容

  • 一个精美的 Affirmations 应用,该应用使用 RecyclerView 显示卡片列表。每张卡片都包含一张图片和一句自我肯定话语文本。

所需条件

  • 一台安装了 Android Studio 4.1 或更高版本的计算机。
  • 能够连接互联网下载图片文件。
  • 上一个 Codelab(即创建 Affirmations 应用)中的 Affirmations 应用(此 Codelab 中不提供起始代码;创建该应用是前提条件)。

2. 向列表项添加图片

到目前为止,您已创建适配器 ItemAdapter 以在 RecyclerView 中显示自我肯定话语字符串。这样可以很好地满足功能方面的要求,但从视觉上看,却不是很有吸引力。在此任务中,您将修改列表项布局和适配器代码以显示图片与自我肯定话语。

下载图片

  1. 首先,在 Android Studio 中打开上一个 Codelab 中的 Affirmations 应用项目。如果您没有该项目,请执行上一个 Codelab 中的步骤以创建该项目。然后返回此处。
  2. 接下来,将图片文件下载到您的计算机上。一共应该有十张图片,应用中的每句自我肯定话语各有一张图片。这些图片文件的名称应该是从 image1.jpgimage10.jpg
  3. 在 Android Studio 中,将图片从计算机复制到项目的 res > drawable 文件夹 (app/src/main/res/drawable) 中。一旦将这些资源添加到应用,您便能够使用资源 ID(如 R.drawable.image1)从代码中访问这些图片(您可能必须重建代码,才能让 Android Studio 找到相应图片)。

现在,图片就可以在应用中使用了。

在 Affirmation 类中添加对图片的支持

在此步骤中,您将在 Affirmation 数据类中添加一个属性来存储图片资源 ID 的值。这样,单个 Affirmation 对象实例将包含自我肯定话语文本的资源 ID 和自我肯定话语图片的资源 ID。

  1. 打开 model 软件包中的 Affirmation.kt 文件。
  2. 添加另一个名为 imageResourceIdInt 形参,从而修改 Affirmation 类的构造函数。

使用资源注解

stringResourceIdimageResourceId 都是整数值。虽然这看起来没有问题,但调用方可能会意外地以错误的顺序传入实参,即首先传入 imageResourceId 而不是 stringResourceId

为避免此问题,您可以使用资源注解。注解很有用,因为它们可以向类、方法或参数添加额外的信息。注解始终使用 @ 符号进行声明。在本例中,向字符串资源 ID 属性添加 @StringRes 注解,并向可绘制资源 ID 属性添加 @DrawableRes 注解。这样一来,如果您提供了错误类型的资源 ID,就会收到警告。

  1. stringResourceId 添加 @StringRes 注解。
  2. imageResourceId 添加 @DrawableRes 注解。
  3. 确保在文件的顶部且在软件包声明后面添加导入代码 androidx.annotation.DrawableResandroidx.annotation.StringRes

Affirmation.kt

package com.example.affirmations.model

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes

data class Affirmation(
   @StringRes val stringResourceId: Int,
   @DrawableRes val imageResourceId: Int
)

初始化带图片的自我肯定话语列表

现在,您已更改 Affirmation 类的构造函数,接下来需要更新 Datasource 类。向初始化的每个 Affirmation 对象传入一个图片资源 ID。

  1. 打开 Datasource.kt。您应该会看到 Affirmation 的每次实例化都有一个错误。
  2. 对于每个 Affirmation,将图片的资源 ID 添加为实参,如 R.drawable.image1

Datasource.kt

package com.example.affirmations.data

import com.example.affirmations.R
import com.example.affirmations.model.Affirmation

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

向列表项布局添加 ImageView

如需为列表中的每句自我肯定话语显示一张图片,您需要向项布局添加 ImageView。由于您现在有两个视图(TextViewImageView),因此需要将它们作为子视图放在 ViewGroup 中。如需在垂直列中排列视图,您可以使用 LinearLayoutLinearLayout 会在一个方向上(垂直或水平)对齐所有子视图。

a5cb4349a970c992.png

  1. 依次打开 res > layout > list_item.xml。围绕现有的 TextView 添加 LinearLayout,并将 orientation 属性设置为 vertical
  2. xmlns schema 声明行从 TextView 元素移至 LinearLayout 元素以消除错误。

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
  1. LinearLayout, 内的 TextView, 前面,添加资源 ID 为 item_imageImageView
  2. ImageView 的宽度设置为 match_parent,并将其高度设置为 194dp。设置此值后,在任何给定时间,屏幕上应该都会显示几张卡片,卡片数量取决于屏幕大小。
  3. scaleType 设置为 centerCrop.
  4. importantForAccessibility 属性设置为 no,因为图片仅用作装饰。
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="194dp"
        android:id="@+id/item_image"
        android:importantForAccessibility="no"
        android:scaleType="centerCrop" />

更新 ItemAdapter 以设置图片

  1. 打开 adapter/ItemAdapter.kt (app > java > adapter > ItemAdapter)。
  2. 找到 ItemViewHolder 类。
  3. ItemViewHolder 实例应在列表项布局中存储对 TextView 的引用以及对 ImageView 的引用。请做以下更改。

textView 属性的初始化下面,添加一个名为 imageViewval。使用 findViewById() 查找对 ImageView(ID 为 item_image)的引用,并将其赋值给 imageView 属性。

ItemAdapter.kt

class ItemViewHolder(private val view: View): RecyclerView.ViewHolder(view) {
    val textView: TextView = view.findViewById(R.id.item_title)
    val imageView: ImageView = view.findViewById(R.id.item_image)
}
  1. ItemAdapter 中查找 onBindViewHolder() 函数。
  2. 之前,您已将自我肯定话语的 stringResourceId 设置到 ItemViewHolder 中的 textView 上。现在,将自我肯定话语项的 imageResourceId 设置到列表项视图的 ImageView 上。
    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val item = dataset[position]
        holder.textView.text = context.resources.getString(item.stringResourceId)
        holder.imageView.setImageResource(item.imageResourceId)
    }
  1. 运行应用并滚动浏览自我肯定话语列表。

485d002900657409.png

有了图片,应用看起来更漂亮了!不过,您仍然可以改进应用界面。在下一部分中,您将对应用进行细微的调整以改进界面。

3. 美化界面

到目前为止,您已经构建了一个可以正常运行的应用,该应用由自我肯定话语字符串和图片列表组成。在本部分中,您将会看到代码和 XML 中的细微更改如何使应用看起来更精美。

添加内边距

首先,在列表中的项之间添加一些空白。

  1. 打开 item_list.xml (app > res > layout > item_list.xml),然后向现有的 LinearLayout 添加 16dp 的内边距。

list_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">
  1. item_title TextView 添加 16dp 的内边距。
  2. TextView 中,将 textAppearance 属性设置为 ?attr/textAppearanceHeadline6textAppearance 是用于定义文本专用样式的属性。如需了解其他可能的预定义文本外观值,请参阅关于常见主题属性的博文中的 TextAppearances 部分。
    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:textAppearance="?attr/textAppearanceHeadline6" />
  1. 运行应用。列表是不是看起来更美观了?

a95304a44a8876d7.png

使用卡片

现在仍然很难分辨一张图片是属于它上面还是下面的自我肯定话语文本。为了解决此问题,您可以使用卡片视图。卡片视图提供了一种简单的方法来包含一组视图,同时又能为容器提供一致的样式。如需更多关于如何使用卡片的 Material Design 指导,请参阅这篇关于卡片的指南

  1. 围绕现有的 LinearLayout 添加 MaterialCardView
  2. 再次将架构声明从 LinearLayout 移入 MaterialCardView
  3. MaterialCardViewlayout_width 设置为 match_parent,并将 layout_height 设置为 wrap_content
  4. 添加 8dplayout_margin
  5. 移除 LinearLayout 中的内边距,这样就不会有太多的空白。
  6. 现在,再次运行应用。使用 MaterialCardView 之后,每句自我肯定话语是不是更方便区分了?

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/item_image"
            android:layout_width="match_parent"
            android:layout_height="194dp"
            android:importantForAccessibility="no"
            android:scaleType="centerCrop" />

        <TextView
            android:id="@+id/item_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:textAppearance="?attr/textAppearanceHeadline6" />

    </LinearLayout>

</com.google.android.material.card.MaterialCardView>

af61b5d2baa66e39.png

更改应用主题颜色

默认应用主题颜色可能不像您自己选择的颜色一样赏心悦目。在此任务中,您会将应用主题颜色更改为蓝色。随后您可以按照自己的想法再次更改颜色!

您可以从此链接的 Material Design 调色板中找到预定义的蓝色色调。

在此 Codelab 中,您将使用 Material Design 调色板中的以下颜色:

  • blue_200:#FF90CAF9
  • blue_500:#FF2196F3
  • blue_700:#FF1976D2

添加颜色资源

在一个集中的位置(即在 colors.xml 文件中)定义应用中使用的颜色。

  1. 打开 colors.xml (res > values > colors.xml)。
  2. 针对下面定义的蓝色向该文件中添加新的颜色资源:
<color name="blue_200">#FF90CAF9</color>
<color name="blue_500">#FF2196F3</color>
<color name="blue_700">#FF1976D2</color>

更改主题颜色

现在,您已经有了新的颜色资源,接下来可以在主题中使用它们了。

  1. 打开 themes.xml (res > values > themes > themes.xml)。
  2. 找到 <!-- Primary brand color. --> 部分。
  3. 添加或更改 colorPrimary 以使用 @color/blue_500
  4. 添加或更改 colorPrimaryVariant 以使用 @color/blue_700
<item name="colorPrimary">@color/blue_500</item>
<item name="colorPrimaryVariant">@color/blue_700</item>
  1. 运行应用。您应该会看到应用栏颜色变成了蓝色。

8d7a20a5d7a079ce.png

更新深色主题颜色

最好为应用的深色主题选择饱和度更低的颜色。

  1. 打开深色主题 themes.xml 文件 (themes > themes.xml (night))。
  2. 添加或更改 colorPrimarycolorPrimaryVariant 主题属性,如下所示:
<item name="colorPrimary">@color/blue_200</item>
<item name="colorPrimaryVariant">@color/blue_500</item>
  1. 运行应用。
  2. 在设备的设置中,开启深色主题

  1. 应用会切换到深色主题。验证它是否看起来像下面的屏幕截图:

6564b21429206ebc.png

  1. 此时,您还可以在 colors.xml 文件中移除未使用的颜色(例如,在默认应用主题中使用的紫色资源)。

更改应用图标

在最后一步中,您将更新应用图标。

  1. 下载应用图标文件 ic_launcher_foreground.xmlic_launcher_background.xml。如果您的浏览器显示了相应的文件而没有下载该文件,请依次选择文件 > 网页另存为…,以将其保存到计算机上。
  2. 在 Android Studio 中,删除两个文件,即 drawable/ic_launcher_background.xmldrawable-v24/ic_launcher_foreground.xml 文件,因为这些文件用于以前的应用图标。您可以取消选中 Safe delete (with usage search) 框。
  3. 然后右键点击 res > drawable 文件夹,再依次选择 New > Image Asset

51e40f30078ad631.png

  1. Configure Image Asset 窗口中,确保选择了 Foreground layer

8c437aa925887439.png

  1. 在它下面,找到 Path 标签。
  2. 点击 Path 文本框内的文件夹图标。
  3. 找到并打开您下载到计算机上的 ic_launcher_foreground.xml 文件。

ddac89ef587fba99.png

  1. 切换到 Background Layer 标签页。
  2. 点击 Path 文本框内的 Browse 图标。
  3. 找到并打开计算机上的 ic_launcher_background.xml 文件。不需要进行其他更改。
  4. 点击 Next

c0c1986d1887afdb.png

  1. Confirm Icon Path 对话框中,点击 Finish。可以覆盖现有图标。
  2. 作为最佳实践,您可以将新的矢量可绘制对象 ic_launcher_foreground.xmlic_launcher_background.xml 移入一个名为 drawable-anydpi-v26 的新资源目录。自适应图标是在 API 26 中引入的,因此这些资源只会用在搭载 API 26 及更高版本(针对任何 dpi)的设备上。
  3. 如果 drawable-v24 目录中没有剩下任何内容,请删除该目录。
  4. 运行应用并注意应用抽屉中漂亮的新应用图标!

649133c325fa9b17.png

  1. 最后,请不要忘记为项目中的 Kotlin 和 XML 文件重新设置格式,使代码更简洁并遵循样式准则。

恭喜!您创建了一个鼓舞人心的 Affirmations 应用。

利用这些关于如何在 Android 应用中显示数据列表的知识,您接下来可以构建什么呢?

4. 解决方案代码

Affirmations 应用的解决方案代码位于下面的 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. 总结

  • 如需在 RecyclerView 中显示其他内容,请修改底层数据模型类和数据源。然后,更新列表项布局和适配器以将该数据设置到视图上。
  • 使用资源注解帮助确保将正确类型的资源 ID 传入类构造函数。
  • 使用 Material Components for Android 库让应用更轻松地遵循建议的 Material Design 准则。
  • 使用 MaterialCardView 在 Material 卡片中显示内容。
  • 在颜色和间距方面对应用进行细微的视觉调整,可使应用看起来更精美且更一致。

6. 了解更多内容

7. 挑战任务

在这一系列 Codelab 中,您学习了如何将 LinearLayoutManagerRecyclerView 搭配使用。RecyclerView 可以使用不同的 LayoutManagers 来以不同的方式设置数据的布局。

  • RecyclerViewlayoutManager 属性设置为 GridLayoutManager
  • 将列数更改为 3。
  • 更改适配器布局以在网格中直观地查看数据。