RecyclerView
Android Development
ScrollToPosition
User Interface
Android UI

Scroll RecyclerView to show selected item on top

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When a user selects an item in a RecyclerView, a common UI requirement is to scroll that item into view and align it with the top of the list. The most reliable way to do that with a vertical list is usually LinearLayoutManager.scrollToPositionWithOffset, optionally wrapped in post so the scroll runs after layout has happened.

Why scrollToPosition is not enough

RecyclerView.scrollToPosition(position) makes sure the item is visible, but it does not guarantee that the item will land at the top. The layout manager is free to place it anywhere that satisfies visibility.

If you specifically want top alignment, you need an API that also accepts an offset. For a vertical LinearLayoutManager, that method is scrollToPositionWithOffset(position, 0).

Basic Kotlin example

Here is the standard pattern:

kotlin
1import androidx.recyclerview.widget.LinearLayoutManager
2import androidx.recyclerview.widget.RecyclerView
3
4fun scrollSelectedItemToTop(
5    recyclerView: RecyclerView,
6    position: Int
7) {
8    val layoutManager = recyclerView.layoutManager as? LinearLayoutManager ?: return
9    layoutManager.scrollToPositionWithOffset(position, 0)
10}

An offset of 0 means "place the item flush with the top edge."

Run the scroll after layout if needed

If you trigger the scroll too early, the RecyclerView may not have finished its layout pass yet. In that case, post the work:

kotlin
1fun scrollSelectedItemToTop(
2    recyclerView: RecyclerView,
3    position: Int
4) {
5    val layoutManager = recyclerView.layoutManager as? LinearLayoutManager ?: return
6
7    recyclerView.post {
8        layoutManager.scrollToPositionWithOffset(position, 0)
9    }
10}

This is especially helpful when the data set has just changed, the adapter has just been attached, or you are restoring selection after navigation.

Handling user selection through the adapter

In many apps, the selection starts in the adapter or fragment. A simple flow looks like this:

kotlin
1class MyFragment : Fragment() {
2
3    private lateinit var recyclerView: RecyclerView
4
5    private fun onItemSelected(position: Int) {
6        val layoutManager = recyclerView.layoutManager as? LinearLayoutManager ?: return
7
8        recyclerView.post {
9            layoutManager.scrollToPositionWithOffset(position, 0)
10        }
11    }
12}

If the selected item should also be visually highlighted, update the adapter state first and then scroll so the top-aligned row is already rendered in its selected style.

Decorations, padding, and restored state

The exact visual result can change if the list uses top padding or an item decoration. In those cases, an offset of 0 aligns the row with the start of the padded content area, not necessarily the very top pixel of the screen. If you want a gap above the selected row, pass a positive offset instead of changing the scroll method.

State restoration matters too. If you reopen the screen and want the previously selected item on top again, restore the selection and then perform the offset scroll after the adapter data is available. Doing it in the opposite order often leads to no-op scrolls. This matters most when the list is repopulated asynchronously from a ViewModel or database query. In practice, many "scroll did nothing" bugs come from timing, not from the scroll method itself.

Common Pitfalls

  • Using scrollToPosition and expecting top alignment.
  • Triggering the scroll before the RecyclerView has finished layout.
  • Forgetting to validate the selected position against the adapter item count.
  • Assuming every layout manager supports scrollToPositionWithOffset; that method is specific to layout managers such as LinearLayoutManager.

Summary

  • Use LinearLayoutManager.scrollToPositionWithOffset(position, 0) when the selected row must appear at the top.
  • Wrap the call in recyclerView.post if the list has not finished layout yet.
  • 'scrollToPosition only guarantees visibility, not top alignment.'
  • Account for padding, decorations, and state restoration when the final placement must be exact.

Course illustration
Course illustration

All Rights Reserved.