1. Welcome
Introduction
One of the main strengths of RecyclerView
is the ability to let you use layout managers to control and modify your layout strategy. A LayoutManager
manages how the items in the RecyclerView
are arranged.
RecyclerView
comes with out-of-the-box layout managers for common use cases. For example, you can use LinearLayout
for horizontal and vertical lists, or GridLayout
for grids. For more complicated use cases, you need to implement a custom LayoutManager
.
In this codelab, you learn how to display data using a grid layout instead of a list, building on the sleep-tracker app from the previous codelab. (If you don't have the app from the previous codelab, you can download starter code for this codelab.)
What you should already know
You should be familiar with:
- Building a basic user interface using an
Activity
,Fragments
, andViews
- Navigating between fragments and using
safeArgs
to pass data between fragments - View models, view model factories, and transformations
LiveData
and their observers- How to create a
Room
database, create a DAO, and define entities - How to use coroutines for database tasks and other long-running tasks
- How to implement a basic
RecyclerView
with anAdapter
,ViewHolder
, and item layout - How to implement data binding for
RecyclerView
- How to create and use binding adapters to transform data
What you'll learn
- How to use a different
LayoutManager
to change how your data is displayed in theRecyclerView
- How to create a grid layout for your sleep data
What you'll do
- Build on the sleep-tracker app from the previous codelab in this series.
- Replace the list of sleep data displayed by the
RecyclerView
in the app with a grid of sleep data.
2. App overview
The sleep-tracker app has two screens, represented by fragments, as shown in the figure below.
The first screen, shown on the left, has buttons for starting and stopping tracking. The screen shows some of the user's sleep data. The Clear button permanently deletes all the data that the app has collected for the user. The second screen, shown on the right, is for selecting a sleep-quality rating.
This app uses a simplified architecture with a UI controller, view model and LiveData
, and a Room
database to persist sleep data.
The sleep data is displayed in a RecyclerView
. In this codelab, you change the app to use a GridLayout
. The final screen will look like the screenshot below.
3. Concept: Layouts and LayoutManagers
In a previous codelab, when you added the RecyclerView
to fragment_sleep_tracker.xml
, you added a LinearLayoutManager
without any customizations. This code displays the data as a vertical list.
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
LinearLayoutManager
is the most common and straightforward layout manager for RecyclerView
, and it supports both horizontal and vertical placement of child views. For example, you could use LinearLayoutManager
to create a carousel of images that the user scrolls horizontally.
GridLayout
Another common use case is needing to show a lot of data to the user, which you can do using GridLayout
. The GridLayoutManager
for RecyclerView
lays out the data as a scrollable grid, as shown below.
From a design perspective, GridLayout
is best for lists that can be represented as icons or images, such as lists within a photo browsing app. In the sleep-tracker app, you could show each night of sleep as a grid of large icons. This design would give the user an overview of their sleep quality at a glance.
How GridLayout lays out items
GridLayout
arranges items in a grid of rows and columns. Assuming vertical scrolling, by default, each item in a row takes up one "span." Sometimes an item can occupy multiple spans. In the case below, one span is equivalent to the width of one column.
In the first two examples shown below, each row is made up of three spans. By default, the GridLayoutManager
lays out each item in one span until the span count, which you specify. When it reaches the span count, it wraps to the next line.
By default, each item takes up one span, but you can make an item wider by specifying how many spans it is to occupy. For example, the top item in the rightmost screen (shown below) takes up three spans.
4. Task: Implement GridLayout
In this task, you take the RecyclerView
that you finished in the last exercise and update it to display data using a GridLayoutManager
. You can continue using the sleep-tracker app from the previous codelab, or you can download the RecyclerViewGridLayout-Starter app from GitHub.
Step 1: Change the LayoutManager
- If needed, download the RecyclerViewGridLayout-Starter app for this codelab from GitHub and open the project in Android Studio.
- Open the
fragment_sleep_tracker.xml
layout file. - Remove the layout manager from the
sleep_list
RecyclerView
definition.
Code to delete:
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager
- Open
SleepTrackerFragment.kt
. - In
OnCreateView()
, just before thereturn
statement, create a new vertical, top-to-bottomGridLayoutManager
with 3 spans.
The GridLayoutManager
constructor takes up to four arguments: a context, which is the activity
, the number spans (columns, in the default vertical layout), an orientation (default is vertical), and whether it's a reverse layout (default is false
).
val manager = GridLayoutManager(activity, 3, GridLayoutManager.VERTICAL, false)
- Below that line, tell the
RecyclerView
to use thisGridLayoutManager
. TheRecyclerView
is in the binding object and is calledsleepList
. (Seefragment_sleep_tracker.xml
.)
binding.sleepList.layoutManager = manager
Step 2: Change the layout
The current layout in list_item_sleep_night.xml
displays the data by using a whole row per night. In this step, you define a more compact square item layout for the grid.
- Open
list_item_sleep_night.xml
. Use the Code view to inspect the XML. - Delete the
sleep_length
TextView
, because the new design doesn't need it. - Move the
quality_string
TextView
so that it displays beneath theImageView
. To do that, you have to update quite a few things. Here is the final layout for thequality_string
TextView
andquality_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!"/>
- Verify in the Design view that the
quality_string
TextView
is positioned below theImageView
.
Because you used data binding, you don't need to change anything in the Adapter
. The code should just work, and your list should display as a grid.
- Run the app and observe how the sleep data is displayed in a grid.
Note that the ConstraintLayout
still takes the entire width. The GridLayoutManager
gives your view a fixed width, based on its span. GridLayoutManager
does its best to meet all constraints when laying out the grid, adding whitespace or clipping items.
- In
SleepTrackerFragment.kt
, in the code that creates theGridLayoutManager
, change the number of spans forGridLayoutManger
to 1. Run the app, and you get a list.
val manager = GridLayoutManager(activity, 1)
- Change the number of spans for
GridLayoutManager
to 10 and run the app. Notice that theGridLayoutManager
will fit 10 items in a row, but the items are now clipped. - Change the span count to 5 and the direction to
GridLayoutManager.
HORIZONTAL
. Run the app and notice how you can scroll horizontally. Pretty cool! It still needs a different layout to improve its look and feel. We can leave that for a future codelab..
val manager = GridLayoutManager(activity, 5, GridLayoutManager.HORIZONTAL, false)
- Don't forget to set the span count back to 3 and the orientation to vertical!
5. Solution code
Android Studio project: RecyclerViewGridLayout
6. Summary
- A Layout manager can be used to determine the arrangement of items in a
RecyclerView
. RecyclerView
comes with built-in layout managers for common use cases such asLinearLayout
for horizontal and vertical lists, andGridLayout
for grids.- For more complicated use cases, you can implement a custom
LayoutManager
. - From a design perspective,
GridLayout
is best used for lists of items that can be represented as icons or images. GridLayout
arranges items in a grid of rows and columns. Assuming vertical scrolling, each item in a row takes up what's called a "span."- You can customize how many spans an item takes up, creating more interesting grids without the need for a custom layout manager.
- Create an item layout for one item in the grid, and the layout manager takes care of arranging the items.
- You can set the
LayoutManager
for theRecyclerView
either in the XML layout file that contains the<RecyclerView>
element, or you can set it programmatically.
7. Learn more
Udacity courses:
Android developer documentation:
8. Homework
This section lists possible homework assignments for students who are working through this codelab as part of a course led by an instructor. It's up to the instructor to do the following:
- Assign homework if required.
- Communicate to students how to submit homework assignments.
- Grade the homework assignments.
Instructors can use these suggestions as little or as much as they want, and should feel free to assign any other homework they feel is appropriate.
If you're working through this codelab on your own, feel free to use these homework assignments to test your knowledge.
Answer these questions
Question 1
Which of the following are layout managers provided by Android? Select all that apply.
▢ LinearLayoutManager
▢ GridLayoutManager
▢ CircularLayoutManager
▢ StaggeredGridLayoutManager
Question 2
What is a "span"?
▢ The size of a grid created by GridLayoutManager
.
▢ The width of a column in the grid.
▢ The dimensions of an item in a grid.
▢ The number of columns in a grid that has a vertical orientation.