Android Kotlin 基础知识:GridLayout 和 RecyclerView

Android Kotlin 基础知识:GridLayout 和 RecyclerView

Sobre este codelab

account_circleEscrito por Google Developers 培训团队

1. 欢迎

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

RecyclerView 的一个主要优势是让您可以使用布局管理器来控制和修改布局策略。LayoutManager 用于管理 RecyclerView 中各项的排列方式。

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

fcf0fc4b78f8650.png

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

您应熟悉以下知识:

  • 使用 ActivityFragmentsViews 构建基本界面
  • 在 fragment 之间导航,并使用 safeArgs 在 fragment 之间传递数据
  • 视图模型、视图模型工厂和转换
  • LiveData 及其观察者
  • 如何创建 Room 数据库,创建 DAO 和定义实体
  • 如何将协程用于数据库任务和其他长时间运行的任务
  • 如何使用 AdapterViewHolder 和项布局实现基本 RecyclerView
  • 如何为 RecyclerView 实现数据绑定
  • 如何创建和使用绑定适配器来转换数据
  • 如何使用不同的 LayoutManager 更改数据在 RecyclerView 中的显示方式
  • 如何为您的睡眠数据创建网格布局
  • 在本系列上一个 Codelab 的睡眠跟踪器应用的基础上进行构建。
  • 将应用中的 RecyclerView 显示的睡眠数据列表替换为睡眠数据网格。

2. 应用概览

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

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

此应用采用简化的架构,其中包括一个界面控制器、ViewModel 和 LiveData,以及一个用于保留睡眠数据的 Room 数据库。

49f975f1e5fe689.png

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

b0abde98c5f99bf6.png

3. 概念:布局和 LayoutManager

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

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

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

GridLayout

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

fcf0fc4b78f8650.png

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

GridLayout 如何布局列表项

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

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

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

4. 任务:实现 GridLayout

在此任务中,您将获取在上一个练习中完成的 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 语句前面,创建一个新的自上而下垂直的 GridLayoutManager,包含 3 个 Span。

GridLayoutManager 构造函数最多可接受四个参数:上下文(即 activity)、span 数(默认垂直布局中的列数)、方向(默认为垂直方向)以及是否是反向布局(默认为 false)。

val manager = GridLayoutManager(activity, 3, GridLayoutManager.VERTICAL, false)
  1. 在该行的下方,告知 RecyclerView 使用此 GridLayoutManagerRecyclerView 位于绑定对象中,并被命名为 sleepList。(请参见 fragment_sleep_tracker.xml。)
binding.sleepList.layoutManager = manager

第 2 步:更改布局

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

  1. 打开 list_item_sleep_night.xml。使用 Code 视图检查 XML。
  2. 删除 sleep_length TextView,因为新设计不需要它。
  3. 移动 quality_string TextView,使其显示在 ImageView 下方。为此,您必须更新几项内容。quality_string TextViewquality_image ImageView 的最终布局如下:
<ImageView
   
android:id="@+id/quality_image"
   
android:layout_width="@dimen/icon_size"
   
android:layout_height="60dp"
   
android:layout_marginTop="8dp"
   
android:layout_marginBottom="8dp"
   
app:layout_constraintBottom_toBottomOf="parent"
   
app:layout_constraintEnd_toEndOf="parent"
   
app:layout_constraintStart_toStartOf="parent"
   
app:layout_constraintTop_toTopOf="parent"
   
tools:srcCompat="@drawable/ic_sleep_5"
   
app:sleepImage="@{sleep}"/>

<TextView
   
android:id="@+id/quality_string"
   
android:layout_width="0dp"
   
android:layout_height="20dp"
   
android:layout_marginEnd="16dp"
   
android:textAlignment="center"
   
app:layout_constraintBottom_toBottomOf="parent"
   
app:layout_constraintEnd_toEndOf="parent"
   
app:layout_constraintHorizontal_bias="0.0"
   
app:layout_constraintStart_toStartOf="parent"
   
app:layout_constraintTop_toBottomOf="@+id/quality_image"
   
app:sleepQualityString="@{sleep}"
   
tools:text="Excellent!"/>
  1. Design 视图中,验证 quality_string TextView 是否位于 ImageView 下方。

969906bdadeaa2dd.png

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

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

请注意,ConstraintLayout 仍会占用整个宽度。GridLayoutManager 会根据视图的 span 为其设置固定宽度。GridLayoutManager 会在放置网格、添加空格或裁剪项时尽可能满足所有约束条件。

  1. SleepTrackerFragment.kt 中,在用于创建 GridLayoutManager 的代码中,将 GridLayoutManger 的 span 数量更改为 1。运行应用,您将会得到一个列表。
val manager = GridLayoutManager(activity, 1)
  1. GridLayoutManager 的 span 数量更改为 10 并运行应用。请注意,GridLayoutManager 将在一行中放置 10 个项,但现在项会被裁剪。
  2. 将 span 数量更改为 5,将方向更改为 GridLayoutManager.HORIZONTAL。运行应用并注意水平滚动状况如何。相当不错!它仍需要不同的布局来改善其外观和风格。我们可以将此任务留到后续 Codelab 中执行。
val manager = GridLayoutManager(activity, 5, GridLayoutManager.HORIZONTAL, false)
  1. 别忘了重新将 span 数量设置为 3,将屏幕方向设置为垂直!

6. 总结

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

8. 家庭作业

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

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

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

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

回答以下问题

问题 1

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

LinearLayoutManager

GridLayoutManager

CircularLayoutManager

StaggeredGridLayoutManager

问题 2

什么是“span”?

GridLayoutManager 创建的网格的大小。

▢ 网格中列的宽度。

▢ 网格中项的尺寸。

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