logo

Education

Building Seamless Scrolling Experiences with Flutter NestedScrollView

Authore Name
Kesar Bhimani

Software Development Executive - I

Authore Name
Nidhi Sorathiya

Software Development Executive - II

Last updated on Oct 27, 2023

Flutter, a popular open-source UI toolkit from Google, provides a wide range of widgets to create complex UIs for your applications. Among these widgets, the NestedScrollView class plays a crucial role in creating scrollable layouts where multiple scrolling views act as one coherent scroll view.

This feature is particularly useful when you have an app bar followed by a tab bar with multiple tabs, each representing different pages. These pages can be swiped horizontally, and each page might have its own scrollable view. The Flutter NestedScrollView widget helps us achieve this effect with ease, adhering to the Material Design specifications.

In this blog post, we will delve into the basics of the NestedScrollView class, its structure, and how to implement it in your Flutter applications. We will also explore how to use it in conjunction with other Flutter widgets like ListView and CustomScrollView. Furthermore, we'll discuss the role of ScrollController in NestedScrollView and how to implement it. Lastly, we will explore the SliverOverlapAbsorber and SliverOverlapInjector widgets and their role in NestedScrollView.

Understanding the Basics of NestedScrollView

What is NestedScrollView and why is it used

NestedScrollView is a class in Flutter that enables multiple scrolling views to act as one coherent scroll view. This widget is particularly useful when you want to create a scrolling view inside another scrolling view, hence the use of the term "nested".

The most common use case for NestedScrollView is when you have an app bar followed by a tab bar with multiple tabs, each representing different pages. These pages can be swiped horizontally, and each page might have its own scrollable view.

In such scenarios, the scroll positions of the outer scroll view and the inner scroll view are intrinsically linked. When the user scrolls up, the app bar scrolls off the screen, and the tab bar sticks to the top. As the user continues to scroll, the inner scroll view starts to scroll. When the user scrolls down, the opposite happens: the inner scroll view scrolls until it hits the top, then the app bar starts coming back.

This overlapping behavior of scroll views is according to the Material Design spec by Google. Significantly, the NestedScrollView widget helps us achieve this effect with ease.

Basic structure and components of NestedScrollView

The NestedScrollView widget takes a required headerSliverBuilder property, which is expected to return a list of widgets that will be slivered and placed in the outer scroll view. The body of the NestedScrollView typically contains the tab views, which are the inner scrolling views.

1 NestedScrollView( 2 headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { 3 return <Widget>[ 4 SliverAppBar( 5 title: const Text('NestedScrollView Example'), 6 pinned: true, 7 floating: true, 8 forceElevated: innerBoxIsScrolled, 9 bottom: TabBar( 10 tabs: List<Widget>.generate(10, (int index) { 11 return Tab(text: 'Tab $index'); 12 }), 13 ), 14 ), 15 ]; 16 }, 17 body: TabBarView( 18 children: List<Widget>.generate(10, (int index) { 19 return SafeArea( 20 top: false, 21 bottom: false, 22 child: Builder( 23 builder: (BuildContext context) { 24 return CustomScrollView( 25 key: PageStorageKey<int>(index), 26 slivers: <Widget>[ 27 SliverOverlapInjector( 28 handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), 29 ), 30 SliverPadding( 31 padding: const EdgeInsets.all(8.0), 32 sliver: SliverFixedExtentList( 33 itemExtent: 48.0, 34 delegate: SliverChildBuilderDelegate( 35 (BuildContext context, int index) { 36 return ListTile( 37 title: Text('Item $index'), 38 ); 39 }, 40 childCount: 30, 41 ), 42 ), 43 ), 44 ], 45 ); 46 }, 47 ), 48 ); 49 }), 50 ), 51 ) 52

In the above example, we have a floating app bar with a tab bar in the headerSliverBuilder. The body contains a TabBarView with multiple tabs. Each tab has its own CustomScrollView, which is the inner scrolling view. The SliverOverlapInjector widget is used to synchronize the scroll positions of the outer and inner scroll views.

The headerSliverBuilder property takes a callback function that provides the current BuildContext and a boolean indicating whether the inner box is scrolled. This callback is expected to return a list of slivers, which are the widgets that will be hosted in the outer scroll view.

In the body of the NestedScrollView, we create a TabBarView that contains the tab views. Each tab view is a separate scrolling view inside the NestedScrollView. The SliverOverlapInjector is used to handle the overlapping of the outer and inner scroll views, ensuring they act as one coherent scroll view.

Getting Started with NestedScrollView

Basic setup requirements for using NestedScrollView

To start using the NestedScrollView widget in your Flutter application, you need to have Flutter SDK installed and set up in your development environment. If you're new to Flutter, you can follow the official Flutter installation guide.

Once you have Flutter set up, you can start creating a new Flutter project or open an existing one. In your project, make sure to import the flutter/material.dart package, which provides the NestedScrollView widget along with many other essential widgets.

1 import 'package:flutter/material.dart'; 2

Simple example of implementing NestedScrollView

Let's create a simple example where we have a floating app bar and a list that scrolls vertically. When the list scrolls, the app bar should scroll off the screen, and when the list reaches the top, the app bar should start coming back.

1 void main() { 2 runApp(MaterialApp( 3 home: Scaffold( 4 body: NestedScrollView( 5 headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { 6 return <Widget>[ 7 SliverAppBar( 8 title: const Text('NestedScrollView Example'), 9 floating: true, 10 pinned: true, 11 forceElevated: innerBoxIsScrolled, 12 ), 13 ]; 14 }, 15 body: ListView.builder( 16 itemCount: 50, 17 itemBuilder: (BuildContext context, int index) { 18 return ListTile( 19 title: Text('List Item $index'), 20 ); 21 }, 22 ), 23 ), 24 ), 25 )); 26 } 27

In this example, we have a NestedScrollView with a SliverAppBar in the headerSliverBuilder. The body of the NestedScrollView contains a ListView.builder that creates a list of ListTile widgets. The floating and pinned properties of the SliverAppBar are set to true, which means the app bar can scroll off the screen and can remain visible at the start of the scroll view.

This example demonstrates how to create a simple NestedScrollView with a floating app bar and a scrolling view inside. When the list scrolls, the app bar scrolls off the screen, creating a seamless user experience.

Exploring the HeaderSliverBuilder

Introduction to HeaderSliverBuilder in NestedScrollView

The headerSliverBuilder is a key property of the NestedScrollView widget. It is a function that should return a list of widgets that will be slivered and placed in the outer scroll view. The headerSliverBuilder takes two parameters: a BuildContext and a boolean value indicating whether the inner box is scrolled.

The BuildContext provides information about the location of a widget in the widget tree, and it can be used to access data that can influence how widgets are built. The boolean value innerBoxIsScrolled indicates whether the inner scroll view or the outer scroll view should react to the user's scroll.

Example of using HeaderSliverBuilder

Let's look at a simple example of using headerSliverBuilder in a NestedScrollView.

1 NestedScrollView( 2 headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { 3 return <Widget>[ 4 SliverAppBar( 5 title: const Text('NestedScrollView Example'), 6 pinned: true, 7 floating: true, 8 forceElevated: innerBoxIsScrolled, 9 bottom: TabBar( 10 tabs: List<Widget>.generate(10, (int index) { 11 return Tab(text: 'Tab $index'); 12 }), 13 ), 14 ), 15 ]; 16 }, 17 body: TabBarView( 18 children: List<Widget>.generate(10, (int index) { 19 return SafeArea( 20 top: false, 21 bottom: false, 22 child: Builder( 23 builder: (BuildContext context) { 24 return CustomScrollView( 25 key: PageStorageKey<int>(index), 26 slivers: <Widget>[ 27 SliverOverlapInjector( 28 handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), 29 ), 30 SliverPadding( 31 padding: const EdgeInsets.all(8.0), 32 sliver: SliverFixedExtentList( 33 itemExtent: 48.0, 34 delegate: SliverChildBuilderDelegate( 35 (BuildContext context, int index) { 36 return ListTile( 37 title: Text('Item $index'), 38 ); 39 }, 40 childCount: 30, 41 ), 42 ), 43 ), 44 ], 45 ); 46 }, 47 ), 48 ); 49 }), 50 ), 51 ) 52

In this example, the headerSliverBuilder returns a SliverAppBar with a TabBar at the bottom. The TabBar contains ten tabs, each represented by a Tab widget. The forceElevated property of the SliverAppBar is set to the value of innerBoxIsScrolled, which means the app bar will show an elevation shadow when the inner scroll view is scrolled.

Combining NestedScrollView with Other Flutter Widgets

Using NestedScrollView with ListView: A beginner’s guide

NestedScrollView can be combined with ListView to create a coherent scroll view where the app bar and the list scroll together. This is useful when you want to create a screen where the app bar scrolls off the screen as the user scrolls through a list.

Here's a simple example of using NestedScrollView with ListView:

1 NestedScrollView( 2 headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { 3 return <Widget>[ 4 SliverAppBar( 5 title: const Text('NestedScrollView with ListView'), 6 floating: true, 7 pinned: true, 8 forceElevated: innerBoxIsScrolled, 9 ), 10 ]; 11 }, 12 body: ListView.builder( 13 itemCount: 50, 14 itemBuilder: (BuildContext context, int index) { 15 return ListTile( 16 title: Text('List Item $index'), 17 ); 18 }, 19 ), 20 ) 21

In this example, the NestedScrollView contains a SliverAppBar in the headerSliverBuilder and a ListView.builder in the body. The ListView.builder creates a list of ListTile widgets. As the list scrolls, the app bar scrolls off the screen, creating a seamless user experience.

Integrating NestedScrollView with CustomScrollView: A simple example

NestedScrollView can also be used with CustomScrollView to create more complex scrollable layouts. CustomScrollView allows you to create a scroll view with slivers, which are portions of a scrollable area that can change their layout.

Here's a simple example of using NestedScrollView with CustomScrollView:

1 NestedScrollView( 2 headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { 3 return <Widget>[ 4 SliverAppBar( 5 title: const Text('NestedScrollView with CustomScrollView'), 6 floating: true, 7 pinned: true, 8 forceElevated: innerBoxIsScrolled, 9 ), 10 ]; 11 }, 12 body: CustomScrollView( 13 slivers: <Widget>[ 14 SliverList( 15 delegate: SliverChildBuilderDelegate( 16 (BuildContext context, int index) { 17 return ListTile( 18 title: Text('List Item $index'), 19 ); 20 }, 21 childCount: 50, 22 ), 23 ), 24 ], 25 ), 26 ) 27

In this example, the NestedScrollView contains a SliverAppBar in the headerSliverBuilder and a CustomScrollView in the body. The CustomScrollView contains a SliverList, which creates a list of ListTile widgets. As the list scrolls, the app bar scrolls off the screen, creating a seamless user experience.

Understanding the ScrollController in NestedScrollView

Role and usage of ScrollController in NestedScrollView

In Flutter, a ScrollController is used to control the position to which a scroll view scrolls. In the context of a NestedScrollView, the ScrollController can be used to control the scroll position of the outer scroll view or the inner scroll views.

The ScrollController is typically used when you want to animate the scroll position, or when you want to know when the scroll position changes, so you can implement some custom behavior.

It's important to note that in a NestedScrollView, the ScrollController you provide is used for the outer scroll view. The inner scroll views are controlled by their own separate ScrollControllers.

Implementing ScrollController in a NestedScrollView example

Let's look at a simple example where we use a ScrollController with a NestedScrollView.

1 ScrollController _scrollController = ScrollController(); 2 3 NestedScrollView( 4 controller: _scrollController, 5 headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { 6 return <Widget>[ 7 SliverAppBar( 8 title: const Text('NestedScrollView with ScrollController'), 9 floating: true, 10 pinned: true, 11 forceElevated: innerBoxIsScrolled, 12 ), 13 ]; 14 }, 15 body: ListView.builder( 16 itemCount: 50, 17 itemBuilder: (BuildContext context, int index) { 18 return ListTile( 19 title: Text('List Item $index'), 20 ); 21 }, 22 ), 23 ) 24

In this example, we create a ScrollController and assign it to the controller property of the NestedScrollView. This allows us to control the scroll position of the outer scroll view. The ListView.builder in the body of the NestedScrollView has its own ScrollController.

Enhance Use Experience with Flutter NestedScrollView!

In this blog post, we've explored the NestedScrollView class in Flutter, a powerful tool for creating complex scrolling views. We've learned about its basic structure, how to implement it, and how to combine it with other Flutter widgets like ListView and CustomScrollView. We've also delved into the role of the ScrollController and how it's used in NestedScrollView, along with the SliverOverlapAbsorber and SliverOverlapInjector widgets.

Understanding and effectively using the NestedScrollView class can significantly enhance the user experience of your Flutter applications, especially when dealing with multiple scrolling views.

We hope this guide has provided you with valuable insights and practical knowledge about the NestedScrollView class.

Short on time? Speed things up with DhiWise!!

Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!

You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.

Sign up to DhiWise for free

Read More