此 Codelab 是“Android Kotlin 基础知识”课程的一部分。如果您按顺序学习这些 Codelab,您将会充分发掘此课程的价值。“Android Kotlin 基础知识”Codelab 着陆页列出了所有课程 Codelab。
简介
RecyclerView
的一个主要优势是让您可以使用布局管理器来控制和修改布局策略。LayoutManager
用于管理 RecyclerView
中各项的排列方式。
RecyclerView
针对常见用例提供开箱即用的布局管理器。例如,对于水平列表和垂直列表您可以使用 LinearLayout
,对于网格您可以使用 GridLayout
。对于更复杂的用例,您需要实现自定义 LayoutManager
。
在此 Codelab 中,您将在上一个 Codelab 的睡眠跟踪器应用的基础上进行构建,学习如何使用网格布局(而非列表)显示数据。(如果您没有上一个 Codelab 的应用,可以下载此 Codelab 的起始代码。)
您应当已掌握的内容
您应熟悉以下知识:
- 使用
Activity
、Fragments
和Views
构建基本界面 - 在 fragment 之间导航,并使用
safeArgs
在 fragment 之间传递数据 - 视图模型、视图模型工厂和转换
LiveData
及其观察者- 如何创建
Room
数据库,创建 DAO 和定义实体 - 如何将协程用于数据库任务和其他长时间运行的任务
- 如何使用
Adapter
、ViewHolder
和项布局实现基本RecyclerView
- 如何为
RecyclerView
实现数据绑定 - 如何创建和使用绑定适配器来转换数据
学习内容
- 如何使用不同的
LayoutManager
更改数据在RecyclerView
中的显示方式 - 如何为您的睡眠数据创建网格布局
实践内容
- 在本系列上一个 Codelab 的睡眠跟踪器应用的基础上进行构建。
- 将应用中的
RecyclerView
显示的睡眠数据列表替换为睡眠数据网格。
此睡眠跟踪器应用有两个屏幕,以 fragment 表示,如下图所示。
左侧所示的第一个屏幕包含用于开始和停止跟踪的按钮。这个屏幕会显示用户的一些睡眠数据。Clear 按钮用于永久删除应用针对用户收集的所有数据。右侧所示的第二个屏幕用于选择睡眠质量评分。
此应用采用简化的架构,其中包括一个界面控制器、ViewModel 和 LiveData
,以及一个用于保留睡眠数据的 Room
数据库。
睡眠数据显示在 RecyclerView
中。在此 Codelab 中,您需要更改应用以使用 GridLayout
。最终的屏幕将如以下屏幕截图所示。
在上一个 Codelab 中,当您将 RecyclerView
添加到 fragment_sleep_tracker.xml
时,您添加了一个没有任何自定义设置的 LinearLayoutManager
。此代码以垂直列表的形式显示数据。
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
LinearLayoutManager
是 RecyclerView
最常用而且最直观的布局管理器,它支持水平和垂直放置子视图。例如,您可以使用 LinearLayoutManager
创建一个图片轮播界面,供用户横向滚动各个图片。
GridLayout
另一个常见用例是需要向用户显示大量数据,您可以使用 GridLayout
执行此操作。RecyclerView
的 GridLayoutManager
将数据设置成可滚动的网格布局,如下所示。
从设计角度来看,GridLayout
最适合可以用图标或图片表示的列表,例如照片浏览应用中的列表。在睡眠跟踪器应用中,您可以用大图标网格的形式显示每晚的睡眠数据。这种设计让用户可以一目了然地了解自己的睡眠质量。
GridLayout 如何布局列表项
GridLayout
将各列表项分成网格的各个行和列。假定您采用的是垂直滚动方式,默认情况下,一行中的每个列表项会占据一个“span”。有时候,一个列表项可以占据多个 span。在下例中,一个 span 相当于一列的宽度。
在下面的前两个示例中,每一行由三个 span 组成。默认情况下,GridLayoutManager
会在一个 span 中布局每个列表项,直到达到您指定的 span 计数为止。达到 span 计数时,它会换行至下一行。
默认情况下,每一项占用一个 span,但您可以通过指定占用的 span 数来扩大项的宽度。例如,最右侧屏幕的顶部项(如下所示)会占用三个 span。
在此任务中,您将获取在上一个练习中完成的 RecyclerView
,并更新它以使用 GridLayoutManager
显示数据。您可以继续使用上一个 Codelab 的睡眠跟踪器应用,也可以从 GitHub 下载 RecyclerViewGridLayout-Starter 应用。
第 1 步:更改 LayoutManager
- 如果需要,请从 GitHub 下载用于此 Codelab 的 RecyclerViewGridLayout-Starter 应用,并在 Android Studio 中打开项目。
- 打开
fragment_sleep_tracker.xml
布局文件。 - 从
sleep_list
RecyclerView
定义中移除布局管理器。
要删除的代码:
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager
- 打开
SleepTrackerFragment.kt
。 - 在
OnCreateView()
中在return
语句前面,创建一个新的自上而下垂直的GridLayoutManager
,包含 3 个 Span。
GridLayoutManager
构造函数最多可接受四个参数:上下文(即 activity
)、span 数(默认垂直布局中的列数)、方向(默认为垂直方向)以及是否是反向布局(默认为 false
)。
val manager = GridLayoutManager(activity, 3, GridLayoutManager.VERTICAL, false)
- 在该行的下方,告知
RecyclerView
使用此GridLayoutManager
。RecyclerView
位于绑定对象中,并被命名为sleepList
。(请参见fragment_sleep_tracker.xml
。)
binding.sleepList.layoutManager = manager
第 2 步:更改布局
list_item_sleep_night.xml
中的当前布局每晚使用一整行显示数据。在此步骤中,您需要为网格定义一个更紧凑的方形项布局。
- 打开
list_item_sleep_night.xml
。使用 Code 视图检查 XML。 - 删除
sleep_length
TextView
,因为新设计不需要它。 - 移动
quality_string
TextView
,使其显示在ImageView
下方。为此,您必须更新几项内容。quality_string
TextView
和quality_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!"/>
- 在 Design 视图中,验证
quality_string
TextView
是否位于ImageView
下方。
因为您使用的是数据绑定,所以不需要更改 Adapter
中的任何内容。代码应该就能正常运行,并且您的列表应以网格形式显示。
- 运行应用并观察睡眠数据在网格中的显示方式。
请注意,ConstraintLayout
仍会占用整个宽度。GridLayoutManager
会根据视图的 span 为其设置固定宽度。GridLayoutManager
会在放置网格、添加空格或裁剪项时尽可能满足所有约束条件。
- 在
SleepTrackerFragment.kt
中,在用于创建GridLayoutManager
的代码中,将GridLayoutManger
的 span 数量更改为 1。运行应用,您将会得到一个列表。
val manager = GridLayoutManager(activity, 1)
- 将
GridLayoutManager
的 span 数量更改为 10 并运行应用。请注意,GridLayoutManager
将在一行中放置 10 个项,但现在项会被裁剪。 - 将 span 数量更改为 5,将方向更改为
GridLayoutManager.
HORIZONTAL
。运行应用并注意水平滚动状况如何。相当不错!它仍需要不同的布局来改善其外观和风格。我们可以将此任务留到后续 Codelab 中执行。
val manager = GridLayoutManager(activity, 5, GridLayoutManager.HORIZONTAL, false)
- 别忘了重新将 span 数量设置为 3,将屏幕方向设置为垂直!
Android Studio 项目:RecyclerViewGridLayout
- 布局管理器可用于确定
RecyclerView
中各项的排列方式。 RecyclerView
附带适用于常见用例的内置布局管理器,例如用于水平列表和垂直列表的LinearLayout
,以及用于网格的GridLayout
。- 对于更复杂的用例,您可以实现自定义
LayoutManager
。 - 从设计角度来看,
GridLayout
最适用于可以用图标或图片表示的项的列表。 GridLayout
将各列表项分成网格的各个行和列。假设采用垂直滚动方式,一行中的每一项都会占据一个“span”。- 您可以自定义某个项占用的 span 数量,从而创建更有趣的网格,而无需自定义布局管理器。
- 为网格中的一项创建项布局,布局管理器会负责排列这些项。
- 您可以在包含
<RecyclerView>
元素的 XML 布局文件中为RecyclerView
设置LayoutManager
,也可以用程序化方式进行设置。
Udacity 课程:
Android 开发者文档:
此部分列出了在由教师指导的课程教学中,学生完成此 Codelab 后可能需要做的家庭作业。教师自行决定是否执行以下措施:
- 根据需要布置作业。
- 告知学生如何提交家庭作业。
- 给家庭作业评分。
教师可以酌情采用这些建议,并且可以自由布置自己认为合适的任何其他家庭作业。
如果您是在自学此 Codelab,可随时通过这些家庭作业来检测您的知识掌握情况。
回答以下问题
问题 1
以下哪些是 Android 提供的布局管理器?请选择所有适用的选项。
▢ LinearLayoutManager
▢ GridLayoutManager
▢ CircularLayoutManager
▢ StaggeredGridLayoutManager
问题 2
什么是“span”?
▢ GridLayoutManager
创建的网格的大小。
▢ 网格中列的宽度。
▢ 网格中项的尺寸。
▢ 垂直方向网格中的列数。
开始学习下一课: