RecyclerView
NestedScrollView
Android Development
UI Components
Android RecyclerView Tutorial

How to use RecyclerView inside NestedScrollView?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Using RecyclerView inside NestedScrollView is a common Android layout request, but it often causes scroll conflicts and performance issues. The best fix is usually to avoid that nesting and let one RecyclerView handle the entire page. If nesting is required, configure scrolling behavior carefully to reduce jank.

Why This Layout Often Breaks

RecyclerView is designed to manage its own scrolling and item recycling. When wrapped in NestedScrollView, measurement can force it to expand fully, which defeats recycling and increases layout cost. This leads to jumpy scroll, poor performance, and unpredictable touch behavior.

Before implementing workarounds, confirm whether a single RecyclerView with multiple view types can replace the nested layout.

Preferred Architecture: Single RecyclerView

A single list with section headers, content blocks, and footers is usually cleaner and faster.

kotlin
1class HomeAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
2    companion object {
3        private const val TYPE_HEADER = 0
4        private const val TYPE_ITEM = 1
5    }
6
7    private val items = mutableListOf<String>()
8
9    override fun getItemViewType(position: Int): Int {
10        return if (position == 0) TYPE_HEADER else TYPE_ITEM
11    }
12
13    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
14        val inflater = LayoutInflater.from(parent.context)
15        return if (viewType == TYPE_HEADER) {
16            val view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
17            object : RecyclerView.ViewHolder(view) {}
18        } else {
19            val view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
20            object : RecyclerView.ViewHolder(view) {}
21        }
22    }
23
24    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
25        val text = holder.itemView.findViewById<TextView>(android.R.id.text1)
26        text.text = if (position == 0) "Header" else items[position - 1]
27    }
28
29    override fun getItemCount(): Int = items.size + 1
30
31    fun submit(data: List<String>) {
32        items.clear()
33        items.addAll(data)
34        notifyDataSetChanged()
35    }
36}

This avoids nested scrolling complexity while keeping UI flexible.

If Nesting Is Unavoidable

When product constraints force nested layout, disable nested scrolling on the inner RecyclerView and let the parent scroll container handle movement.

kotlin
1val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
2recyclerView.layoutManager = LinearLayoutManager(this)
3recyclerView.adapter = HomeAdapter()
4recyclerView.isNestedScrollingEnabled = false

Also keep item counts modest when using this approach, because recycling benefits are reduced.

XML Setup Example

Use fillViewport on the parent so content occupies available space and avoid unnecessary nested wrappers.

xml
1<androidx.core.widget.NestedScrollView
2    android:layout_width="match_parent"
3    android:layout_height="match_parent"
4    android:fillViewport="true">
5
6    <LinearLayout
7        android:layout_width="match_parent"
8        android:layout_height="wrap_content"
9        android:orientation="vertical">
10
11        <TextView
12            android:layout_width="match_parent"
13            android:layout_height="wrap_content"
14            android:text="Section Title" />
15
16        <androidx.recyclerview.widget.RecyclerView
17            android:id="@+id/recyclerView"
18            android:layout_width="match_parent"
19            android:layout_height="wrap_content"
20            android:nestedScrollingEnabled="false" />
21
22    </LinearLayout>
23</androidx.core.widget.NestedScrollView>

Keep this pattern as a fallback, not a default architecture.

Smooth Scrolling and Adapter Practices

Even with recommended layout choices, adapter and binding logic can still introduce jank. Use ListAdapter with DiffUtil for incremental updates instead of full refresh calls.

kotlin
1class RowDiff : DiffUtil.ItemCallback<String>() {
2    override fun areItemsTheSame(oldItem: String, newItem: String): Boolean = oldItem == newItem
3    override fun areContentsTheSame(oldItem: String, newItem: String): Boolean = oldItem == newItem
4}
5
6class RowAdapter : ListAdapter<String, RowAdapter.RowHolder>(RowDiff()) {
7    class RowHolder(view: View) : RecyclerView.ViewHolder(view)
8
9    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RowHolder {
10        val view = LayoutInflater.from(parent.context)
11            .inflate(android.R.layout.simple_list_item_1, parent, false)
12        return RowHolder(view)
13    }
14
15    override fun onBindViewHolder(holder: RowHolder, position: Int) {
16        holder.itemView.findViewById<TextView>(android.R.id.text1).text = getItem(position)
17    }
18}

Incremental list updates reduce relayout work and improve perceived scroll quality.

Compose Alternative for Mixed Content Screens

For new Android codebases, Jetpack Compose often removes the need for nested scroll workarounds. You can express mixed sections in one LazyColumn and keep scrolling behavior unified.

kotlin
1@Composable
2fun HomeScreen(items: List<String>) {
3    LazyColumn {
4        item {
5            Text(text = "Header", modifier = Modifier.padding(16.dp))
6        }
7        items(items) { row ->
8            Text(text = row, modifier = Modifier.padding(16.dp))
9        }
10    }
11}

If your app is gradually migrating, this can be a long-term way to simplify complex nested layout trees.

Debug Checklist for Nested Scroll Issues

Use Android Studio profiler and layout inspector to confirm where time is spent. Check view hierarchy depth, binder thread stalls, and UI thread frame drops. A small checklist during development can prevent shipping scroll regressions.

Common Pitfalls

  • Nesting large RecyclerView lists inside scroll views and losing recycling benefits.
  • Forgetting to disable nested scrolling on the inner list.
  • Treating layout symptoms instead of redesigning to one RecyclerView.
  • Calling notifyDataSetChanged excessively and causing extra layout work.

Summary

  • Prefer one RecyclerView with multiple item view types.
  • Use nested scrolling only when strictly required by layout constraints.
  • If nested, disable inner nested scrolling and simplify hierarchy.
  • Profile scrolling performance early on real devices.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.