Stay organized with collections
Save and categorize content based on your preferences.
Customize a dynamic list
Part of Android Jetpack.
Try the Compose way
Jetpack Compose is the recommended UI toolkit for Android. Learn how to work with layouts in Compose.
You can customize
RecyclerView
objects to meet your specific needs. The standard classes described in
Create dynamic lists with
RecyclerView provide all the functionality that most developers need. In
many cases, you only need to design the view for each view holder and write the
code to update those views with the appropriate data. However, if your app has
specific requirements, you can modify the standard behavior in a number of ways.
This document describes some of the possible customizations.
Modify the layout
RecyclerView
uses a layout manager to position the individual
items on the screen and to determine when to reuse item views that are no longer
visible to the user. To reuse—or recycle—a view, a layout
manager might ask the adapter to replace the contents of the view with a
different element from the dataset. Recycling views this way improves
performance by avoiding the creation of unnecessary views or performing
expensive
findViewById()
lookups. The Android Support Library includes three standard layout managers,
ach of which offers many customization options:
LinearLayoutManager
:
arranges the items in a one-dimensional list. Using a
RecyclerView
with LinearLayoutManager
provides
functionality like a
ListView
layout.
GridLayoutManager
:
arranges the items in a two-dimensional grid, like the squares on a
checkerboard. Using a RecyclerView
with
GridLayoutManager
provides functionality like a
GridView
layout.
StaggeredGridLayoutManager
:
arranges the items in a two-dimensional grid, with each column slightly offset
from the one before, like the stars on an American flag.
If these layout managers don't suit your needs, you can create your own by
extending the
RecyclerView.LayoutManager
abstract class.
Add item animations
Whenever an item changes, RecyclerView
uses an animator
to change its appearance. This animator is an object that extends the abstract
RecyclerView.ItemAnimator
class. By default, the RecyclerView
uses
DefaultItemAnimator
to provide the animation. If you want to provide custom animations, you can
define your own animator object by extending
RecyclerView.ItemAnimator
.
Enable list-item selection
The
recyclerview-selection
library lets users select items in a RecyclerView
list using touch
or mouse input. This lets you retain control over the visual presentation of a
selected item. You can also retain control over policies controlling selection
behavior, such as which items are eligible for selection and how many items can
be selected.
To add selection support to a RecyclerView
instance, follow
these steps:
- Determine which selection key type to use, then build an
ItemKeyProvider
.
There are three key types you can use to identify selected items:
For detailed information about selection-key types, see
SelectionTracker.Builder
.
- Implement
ItemDetailsLookup
.
ItemDetailsLookup
lets the selection library access
information about RecyclerView
items given a
MotionEvent
.
It is effectively a factory for
ItemDetails
instances that are backed up by, or extracted from, a
RecyclerView.ViewHolder
instance.
- Update item
View
objects in
the RecyclerView
to reflect whether the user selects or
unselects them.
The selection library doesn't provide a default visual decoration for the
selected items. Provide this when you implement
onBindViewHolder()
.
We recommend the following approach:
- In
onBindViewHolder()
, call
setActivated()
—not
setSelected()
—on
the View
object with
true
or false
, depending on whether the item
is selected.
- Update the styling of the view to represent the activated status. We
recommend using a
color state
list resource to configure the styling.
- Use
ActionMode
to provide the user with tools to perform an action on the selection.
Register a
SelectionTracker.SelectionObserver
to be notified when a selection changes. When a selection is first created,
start ActionMode
to present this to the user and provide
selection-specific actions. For example, you can add a delete button to the
ActionMode
bar and connect the back arrow on the bar to clear
the selection. When the selection becomes empty—if the user clears the
selection the last time—terminate action mode.
- Perform any interpreted secondary actions.
At the end of the event processing pipeline, the library might determine
that the user is attempting to activate an item, by tapping it, or is
attempting to drag an item or set of selected items. React to these
interpretations by registering the appropriate listener. For more
information, see
SelectionTracker.Builder
.
- Assemble everything with
SelectionTracker.Builder
.
The following example shows how to put these pieces together:
Kotlin
var tracker = SelectionTracker.Builder(
"my-selection-id",
recyclerView,
StableIdKeyProvider(recyclerView),
MyDetailsLookup(recyclerView),
StorageStrategy.createLongStorage())
.withOnItemActivatedListener(myItemActivatedListener)
.build()
Java
SelectionTracker tracker = new SelectionTracker.Builder<>(
"my-selection-id",
recyclerView,
new StableIdKeyProvider(recyclerView),
new MyDetailsLookup(recyclerView),
StorageStrategy.createLongStorage())
.withOnItemActivatedListener(myItemActivatedListener)
.build();
To build a
SelectionTracker
instance, your app must supply the same
RecyclerView.Adapter
that you use to initialize RecyclerView
to
SelectionTracker.Builder
. For this reason, after you create the
SelectionTracker
instance, inject it into your
RecyclerView.Adapter
. Otherwise, you can't check an item's
selected status from the onBindViewHolder()
method.
- Include selection in the
activity
lifecycle events.
To preserve selection state across the activity lifecycle events, your app
must call the selection tracker's
onSaveInstanceState()
and
onRestoreInstanceState()
methods from the activity's
onSaveInstanceState()
and
onRestoreInstanceState()
methods, respectively. Your app must also supply a unique selection ID to the
SelectionTracker.Builder
constructor. This ID is required because
an activity or a fragment might have more than one distinct, selectable list,
all of which need to be persisted in their saved state.
Additional resources
See the following references for additional information.
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2025-08-26 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-26 UTC."],[],[],null,["# Customize a dynamic list\nPart of [Android Jetpack](/jetpack).\n=============================================================\n\nTry the Compose way \nJetpack Compose is the recommended UI toolkit for Android. Learn how to work with layouts in Compose. \n[Lazy Lists and Grids →](/jetpack/compose/lists#lazy) \n\nYou can customize\n[RecyclerView](/reference/androidx/recyclerview/widget/RecyclerView)\nobjects to meet your specific needs. The standard classes described in\n[Create dynamic lists with\nRecyclerView](/guide/topics/ui/layout/recyclerview) provide all the functionality that most developers need. In\nmany cases, you only need to design the view for each view holder and write the\ncode to update those views with the appropriate data. However, if your app has\nspecific requirements, you can modify the standard behavior in a number of ways.\nThis document describes some of the possible customizations.\n\nModify the layout\n-----------------\n\n`RecyclerView` uses a layout manager to position the individual\nitems on the screen and to determine when to reuse item views that are no longer\nvisible to the user. To reuse---or *recycle* ---a view, a layout\nmanager might ask the adapter to replace the contents of the view with a\ndifferent element from the dataset. Recycling views this way improves\nperformance by avoiding the creation of unnecessary views or performing\nexpensive\n[findViewById()](/reference/android/app/Activity#findViewById(int))\nlookups. The Android Support Library includes three standard layout managers,\nach of which offers many customization options:\n\n- [LinearLayoutManager](/reference/androidx/recyclerview/widget/LinearLayoutManager): arranges the items in a one-dimensional list. Using a `RecyclerView` with `LinearLayoutManager` provides functionality like a [ListView](/reference/android/widget/ListView) layout.\n- [GridLayoutManager](/reference/androidx/recyclerview/widget/GridLayoutManager): arranges the items in a two-dimensional grid, like the squares on a checkerboard. Using a `RecyclerView` with `GridLayoutManager` provides functionality like a [GridView](/reference/android/widget/GridView) layout.\n- [StaggeredGridLayoutManager](/reference/androidx/recyclerview/widget/StaggeredGridLayoutManager): arranges the items in a two-dimensional grid, with each column slightly offset from the one before, like the stars on an American flag.\n\nIf these layout managers don't suit your needs, you can create your own by\nextending the\n[RecyclerView.LayoutManager](/reference/androidx/recyclerview/widget/RecyclerView.LayoutManager)\nabstract class.\n\nAdd item animations\n-------------------\n\nWhenever an item changes, `RecyclerView` uses an *animator*\nto change its appearance. This animator is an object that extends the abstract\n[RecyclerView.ItemAnimator](/reference/androidx/recyclerview/widget/RecyclerView.ItemAnimator)\nclass. By default, the `RecyclerView` uses\n[DefaultItemAnimator](/reference/androidx/recyclerview/widget/DefaultItemAnimator)\nto provide the animation. If you want to provide custom animations, you can\ndefine your own animator object by extending\n`RecyclerView.ItemAnimator`.\n\nEnable list-item selection\n--------------------------\n\nThe\n[`recyclerview-selection`](/reference/androidx/recyclerview/selection/package-summary)\nlibrary lets users select items in a `RecyclerView` list using touch\nor mouse input. This lets you retain control over the visual presentation of a\nselected item. You can also retain control over policies controlling selection\nbehavior, such as which items are eligible for selection and how many items can\nbe selected.\n\nTo add selection support to a `RecyclerView` instance, follow\nthese steps:\n\n1. Determine which selection key type to use, then build an [`ItemKeyProvider`](/reference/androidx/recyclerview/selection/ItemKeyProvider).\n\n There are three key types you can use to identify selected items:\n - [Parcelable](/reference/android/os/Parcelable) and its subclasses, like [Uri](/reference/android/net/Uri)\n - [String](/reference/java/lang/String)\n - [Long](/reference/java/lang/Long)\n\n For detailed information about selection-key types, see\n [SelectionTracker.Builder](/reference/androidx/recyclerview/selection/SelectionTracker.Builder).\n2. Implement [ItemDetailsLookup](/reference/androidx/recyclerview/selection/ItemDetailsLookup).\n3. `ItemDetailsLookup` lets the selection library access information about `RecyclerView` items given a [MotionEvent](/reference/android/view/MotionEvent). It is effectively a factory for [`ItemDetails`](/reference/androidx/recyclerview/selection/ItemDetailsLookup.ItemDetails) instances that are backed up by, or extracted from, a [RecyclerView.ViewHolder](/reference/androidx/recyclerview/widget/RecyclerView.ViewHolder) instance.\n4. Update item [View](/reference/android/view/View) objects in the `RecyclerView` to reflect whether the user selects or unselects them.\n\n The selection library doesn't provide a default visual decoration for the\n selected items. Provide this when you implement\n [onBindViewHolder()](/reference/androidx/recyclerview/widget/RecyclerView.Adapter#onBindViewHolder(VH, int)).\n We recommend the following approach:\n - In `onBindViewHolder()`, call [setActivated()](/reference/android/view/View#setActivated(boolean))---**not** [setSelected()](/reference/android/view/View#setSelected(boolean))---on the `View` object with `true` or `false`, depending on whether the item is selected.\n - Update the styling of the view to represent the activated status. We recommend using a [color state\n list resource](/guide/topics/resources/color-list-resource) to configure the styling.\n5. Use [ActionMode](/reference/androidx/appcompat/view/ActionMode) to provide the user with tools to perform an action on the selection.\n6. Register a [SelectionTracker.SelectionObserver](/reference/androidx/recyclerview/selection/SelectionTracker.SelectionObserver) to be notified when a selection changes. When a selection is first created, start `ActionMode` to present this to the user and provide selection-specific actions. For example, you can add a delete button to the `ActionMode` bar and connect the back arrow on the bar to clear the selection. When the selection becomes empty---if the user clears the selection the last time---terminate action mode.\n7. Perform any interpreted secondary actions.\n8. At the end of the event processing pipeline, the library might determine that the user is attempting to activate an item, by tapping it, or is attempting to drag an item or set of selected items. React to these interpretations by registering the appropriate listener. For more information, see [SelectionTracker.Builder](/reference/androidx/recyclerview/selection/SelectionTracker.Builder).\n9. Assemble everything with `SelectionTracker.Builder`.\n10. The following example shows how to put these pieces together: \n\n### Kotlin\n\n```kotlin\n var tracker = SelectionTracker.Builder(\n \"my-selection-id\",\n recyclerView,\n StableIdKeyProvider(recyclerView),\n MyDetailsLookup(recyclerView),\n StorageStrategy.createLongStorage())\n .withOnItemActivatedListener(myItemActivatedListener)\n .build()\n \n```\n\n### Java\n\n```java\n SelectionTracker tracker = new SelectionTracker.Builder\u003c\u003e(\n \"my-selection-id\",\n recyclerView,\n new StableIdKeyProvider(recyclerView),\n new MyDetailsLookup(recyclerView),\n StorageStrategy.createLongStorage())\n .withOnItemActivatedListener(myItemActivatedListener)\n .build();\n \n```\n11. To build a [SelectionTracker](/reference/androidx/recyclerview/selection/SelectionTracker) instance, your app must supply the same [RecyclerView.Adapter](/reference/androidx/recyclerview/widget/RecyclerView.Adapter) that you use to initialize `RecyclerView` to `SelectionTracker.Builder`. For this reason, after you create the `SelectionTracker` instance, inject it into your `RecyclerView.Adapter`. Otherwise, you can't check an item's selected status from the `onBindViewHolder()` method.\n12. Include selection in the [activity\n lifecycle](/guide/components/activities/activity-lifecycle) events.\n13. To preserve selection state across the activity lifecycle events, your app must call the selection tracker's [onSaveInstanceState()](/reference/androidx/recyclerview/selection/SelectionTracker#onSaveInstanceState(android.os.Bundle)) and [onRestoreInstanceState()](/reference/androidx/recyclerview/selection/SelectionTracker#onRestoreInstanceState(android.os.Bundle)) methods from the activity's [onSaveInstanceState()](/reference/android/app/Activity#onSaveInstanceState(android.os.Bundle)) and [onRestoreInstanceState()](/reference/android/app/Activity#onRestoreInstanceState(android.os.Bundle)) methods, respectively. Your app must also supply a unique selection ID to the `SelectionTracker.Builder` constructor. This ID is required because an activity or a fragment might have more than one distinct, selectable list, all of which need to be persisted in their saved state.\n\nAdditional resources\n--------------------\n\nSee the following references for additional information.\n\n- [Sunflower\n demo app](https://github.com/googlesamples/android-sunflower), which uses `RecyclerView`.\n- [Use\n RecyclerView to display a scrollable list](/codelabs/basic-android-kotlin-training-recyclerview-scrollable-list#0) codelab.\n- [Android\n Kotlin Fundamentals: RecyclerView fundamentals](/codelabs/kotlin-android-training-recyclerview-fundamentals) codelab."]]