Android Kotlin 基础知识 07.3:将 GridLayout 与 RecyclerView

此 Codelab 是“Android Kotlin 基础知识”课程的一部分。如果您按顺序学习这些 Codelab,您将会充分发掘此课程的价值。“Android Kotlin 基础知识”Codelab 着陆页列出了所有课程 Codelab。

简介

RecyclerView 的主要优势之一是,它可让您使用布局管理器来控制和修改布局策略。LayoutManager 用于管理 RecyclerView 中内容的排列方式。

RecyclerView 针对常见用例提供开箱即用的布局管理器。例如,对于水平列表和垂直列表您可以使用 LinearLayout,对于网格您可以使用 GridLayout。对于更复杂的用例,您需要实现自定义 LayoutManager

在此 Codelab 中,您将在上一个 Codelab 的睡眠跟踪器应用的基础上进行构建,学习如何使用网格布局(而非列表)显示数据。(如果您没有上一个 Codelab 的应用,可以下载此 Codelab 的起始代码。)

您应当已掌握的内容

您应熟悉以下内容/操作:

  • 使用 ActivityFragmentsViews 构建基本界面
  • 在 fragment 之间导航,并使用 safeArgs 在 fragment 之间传递数据
  • 视图模型、视图模型工厂和转换
  • LiveData 及其观察者
  • 如何创建 Room 数据库,创建 DAO 和定义实体
  • 如何将协程用于数据库任务和其他长时间运行的任务
  • 如何使用 AdapterViewHolder 和项布局实现基本 RecyclerView
  • 如何为 RecyclerView 实现数据绑定
  • 如何创建和使用绑定适配器来转换数据

学习内容

  • 如何使用不同的 LayoutManager 更改数据在 RecyclerView 中的显示方式
  • 如何为您的睡眠数据创建网格布局

实践内容

  • 在本系列上一个 Codelab 的睡眠跟踪器应用的基础上进行构建。
  • 将应用中的 RecyclerView 显示的睡眠数据列表替换为睡眠数据网格。

睡眠跟踪器应用有两个屏幕(由 fragment 表示),如下图所示。

左侧所示的第一个屏幕包含用于开始和停止跟踪的按钮。这个屏幕会显示用户的一些睡眠数据。CLEAR 按钮用于永久删除应用针对用户收集的所有数据。右侧所示的第二个屏幕用于选择睡眠质量评分。

此应用使用简化的架构,其中包含界面控制器、视图模型和 LiveData,以及 Room 数据库以持久存储睡眠数据。

睡眠数据显示在 RecyclerView 中。在此 Codelab 中,您需要更改应用以使用 GridLayout。最终屏幕将如以下屏幕截图所示。

在上一个 Codelab 中,当您将 RecyclerView 添加到 fragment_sleep_tracker.xml 时,您添加了一个没有任何自定义设置的 LinearLayoutManager。此代码以垂直列表的形式显示数据。

app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"

LinearLayoutManagerRecyclerView 最常用而且最直观的布局管理器,它支持水平和垂直放置子视图。例如,您可以使用 LinearLayoutManager 创建一个图片轮播界面,供用户横向滚动各个图片。

GridLayout

另一个常见用例是需要向用户显示大量数据,您可以使用 GridLayout 执行此操作。RecyclerViewGridLayoutManager 将数据布局为可滚动的网格,如下所示。

从设计角度来看,GridLayout 最适合可以用图标或图片表示的列表,例如照片浏览应用中的列表。在睡眠跟踪器应用中,您可以用大图标网格的形式显示每晚的睡眠数据。这种设计让用户可以一目了然地了解自己的睡眠质量。

GridLayout 如何布局列表项

GridLayout 将各列表项分成网格的各个行和列。假定您采用的是垂直滚动方式,默认情况下,一行中的每个列表项会占据一个“span”。(在这种情况下,一个 span 相当于一列的宽度。)

在下面的前两个示例中,每一行由三个 span 组成。默认情况下,GridLayoutManager 会在一个 span 中布局每个列表项,直到达到您指定的 span 计数为止。达到 span 计数时,它会换行至下一行。

默认情况下,每一项占用一个 span,但您可以通过指定占用的 span 数来扩大项的宽度。例如,最右侧屏幕的顶部项(如下所示)会占用三个 span。

在此任务中,您将获取在上一个练习中完成的 RecyclerView,并更新它以使用 GridLayoutManager 显示数据。您可以继续使用上一个 Codelab 中的睡眠跟踪器应用,也可以从 GitHub 下载 RecyclerViewGridLayout-Starter 应用

第 1 步:更改 LayoutManager

  1. 如果需要,请从 GitHub 下载此 Codelab 的 RecyclerViewGridLayout-Starter 应用,并在 Android Studio 中打开项目。
  2. 打开 fragment_sleep_tracker.xml 布局文件。
  3. sleep_list RecyclerView 定义中移除布局管理器。

要删除的代码:

app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager
  1. 打开 SleepTrackerFragment.kt
  2. OnCreateView() 中的 return 语句前面,创建包含 3 个 Span 的新垂直方向(从上到下)。

    GridLayoutManager 构造函数最多接受四个参数:上下文,即 activity;数字跨度(默认垂直布局中的列);方向(默认为垂直);方向是否为反向布局(默认为 false)。
val manager = GridLayoutManager(activity, 3)
  1. 在该行的下方,告知 RecyclerView 使用此 GridLayoutManagerRecyclerView 位于绑定对象中,并被命名为 sleepList。(请参见 fragment_sleep_tracker.xml。)
binding.sleepList.layoutManager = manager

第 2 步:更改布局

list_item_sleep_night.xml 中的当前布局每晚使用一整行显示数据。在此步骤中,您将为网格定义一个更紧凑的方形项目布局。

  1. 打开 list_item_sleep_night.xml
  2. 删除 sleep_length TextView,因为新设计不需要它。
  3. 移动 quality_string TextView,使其显示在 ImageView 下方。为此,您必须更新几项内容。下面是 quality_string TextView 的最终布局:
<TextView
   android:id="@+id/quality_string"
   android:layout_width="0dp"
   android:layout_height="20dp"
   android:textAlignment="center"
   app:layout_constraintBottom_toBottomOf="parent"
   app:layout_constraintEnd_toEndOf="@+id/quality_image"
   app:layout_constraintHorizontal_bias="0.0"
   app:layout_constraintStart_toStartOf="@+id/quality_image"
   app:layout_constraintTop_toBottomOf="@+id/quality_image"
   tools:text="Excellent!!!"
   app:sleepQualityString="@{sleep}" />
  1. Design 视图中,验证 quality_string TextView 是否位于 ImageView 下方。

因为您使用的是数据绑定,所以不需要更改 Adapter 中的任何内容。代码应该就能正常运行,并且您的列表应以网格形式显示。

  1. 运行应用并观察睡眠数据在网格中的显示方式。

    请注意,ConstraintLayout 仍会采用整个宽度。GridLayoutManager 会根据视图的跨距为其提供固定宽度。GridLayoutManager 在布局网格、添加空格或裁剪内容时,会尽力满足所有约束条件。
  1. SleepTrackerFragment 中,在用于创建 GridLayoutManager 的代码中,将 GridLayoutManger 的 span 数量更改为 1。运行应用,您会看到一个列表。
val manager = GridLayoutManager(activity, 1)
  1. GridLayoutManager 的 Span 数量更改为 10 并运行应用。请注意,GridLayoutManager 适合连续放置 10 个项目,但这些项目现在会被裁剪。
  2. 将跨度计数更改为 5,将方向更改为 GridLayoutManager.VERTICAL。运行应用并注意水平滚动状况如何。您需要一个不同的布局来改善外观。
val manager = GridLayoutManager(activity, 5, GridLayoutManager.HORIZONTAL, false)
  1. 别忘了将跨距计数设置回 3 并将方向重置为垂直!

Android Studio 项目:RecyclerViewGridLayout

  • 布局管理器用于管理 RecyclerView 中内容的排列方式。
  • RecyclerView 具有适用于常见用例的开箱即用布局管理器,例如用于水平和垂直列表的 LinearLayout,以及用于网格的 GridLayout
  • 对于更复杂的用例,请实现自定义 LayoutManager
  • 从设计角度来看,GridLayout 最适用于可以用图标或图片表示的项的列表。
  • GridLayout 将各列表项分成网格的各个行和列。假设垂直滚动,一行中的每个列表项都会占用所谓的“跨度”。
  • 您可以自定义某个项的 span 数,从而创建更有趣的网格,而无需自定义布局管理器。
  • 为网格中的一项创建项布局,布局管理器负责排列这些项。
  • 您可以在包含 <RecyclerView> 元素的 XML 布局文件中为 RecyclerView 设置 LayoutManager,或以编程方式设置。

Udacity 课程:

Android 开发者文档:

此部分列出了在由讲师主导的课程中,学生学习此 Codelab 后可能需要完成的家庭作业。讲师自行决定是否执行以下操作:

  • 根据需要布置作业。
  • 告知学生如何提交家庭作业。
  • 给家庭作业评分。

讲师可以酌情采纳这些建议,并且可以自由布置自己认为合适的任何其他家庭作业。

如果您是在自学此 Codelab,可随时通过这些家庭作业来检测您的知识掌握情况。

回答以下问题

问题 1

以下哪些是 Android 提供的布局管理器?请选择所有适用的选项。

LinearLayouManager

GridLayoutManager

CircularLayoutManager

StaggeredGridLayoutManager

问题 2

什么是“跨度”?

GridLayoutManager创建的网格大小。

▢ 网格中列宽。

▢ 网格中项目的尺寸。

▢ 垂直方向网格中的列数。

开始学习下一课:7.4: 与 RecyclerView 项交互