Photo by Wilmer Martinez on Unsplash

We've been discussing scrolling widgets in a series of articles.

Today our topic revolves around Custom Scroll View.

Before we use CustomScrollView, let's know what it is. The CustomScrollView is a ScrollView that uses slivers. And the slivers create various scrolling effects.

How the slivers create various scrolling effects, we'll see in a minute.

Let's see the first screenshot.

CustomScrollView flutter
CustomScrollView flutter

If we check the code of this flutter app, we'll find that we've used AppBar and besides, we've also used SliverAppBar inside the CustomScrollView slivers. As a result, when we press the plus button in the AppBar, the items are being added in the inner space and as we scroll down, the SliverAppBar shrinks.

CustomScrollView with collapsing toolbar
CustomScrollView with collapsing toolbar

The AppBar remains at its place and, SliverAppBar starts working as a collapsing toolbar.

Let's go through the code from the very beginning, so that we can understand how the CustomScrollView works.

Firstly, we need to run the app.

 import 'package:flutter/material.dart'; import 'custom_and_nested_scroll/custom_scroll_sample.dart';  import 'package:provider/provider.dart'; import 'models/counter.dart'; void main() {   runApp(          MultiProvider(       providers: [         ChangeNotifierProvider(           create: (_) => Counter(),         ),       ],              child: CustomScrollSample(),     ),   ); } 

We've used the latest Provider package to maintain our state and increment the item's index.

 import 'package:flutter/foundation.dart';  class Counter with ChangeNotifier {   int _count = 0;    int get count => _count;    void increment() {     _count++;     notifyListeners();   } } 

Next, we've used Scaffold and through the body parameter we use a CustomScrollView.

 import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '/models/counter.dart';  class CustomScrollSample extends StatelessWidget {   const CustomScrollSample({Key? key}) : super(key: key);    @override   Widget build(BuildContext context) {     return MaterialApp(       title: 'CustomScroll Sample',       home: CustomScrollHome(),     );   } }  class CustomScrollHome extends StatelessWidget {   CustomScrollHome({Key? key}) : super(key: key);   List<int> top = <int>[];   List<int> bottom = <int>[0];    @override   Widget build(BuildContext context) {     int index = context.watch<Counter>().count;     const Key centerKey = ValueKey<String>('bottom-sliver-list');     return Scaffold(       appBar: AppBar(         title: const Text('Press to add items above and below'),         leading: IconButton(           icon: const Icon(Icons.add),           onPressed: () {             top.add(-top.length - 1);             bottom.add(bottom.length);             context.read<Counter>().increment();           },         ),       ),       body: CustomScrollView(         slivers: [           SliverAppBar(             expandedHeight: 200.0,             floating: false,             pinned: true,             flexibleSpace: FlexibleSpaceBar(               centerTitle: true,               title: const Text(                 'It will collapse',                 style: TextStyle(                   color: Colors.white,                   fontSize: 16.0,                 ),               ),               background: Image.network(                 'https://cdn.pixabay.com/photo/2016/09/10/17/18/book-1659717_960_720.jpg',                 fit: BoxFit.cover,               ),             ),           ),           SliverList(             delegate: SliverChildBuilderDelegate(               (BuildContext context, int index) {                 return Container(                   alignment: Alignment.center,                   color: Colors.blue[200 + top[index] % 4 * 100],                   height: 100 + top[index] % 4 * 20.0,                   child: Text('Item: ${top[index]}'),                 );               },               childCount: top.length,             ),           ),           SliverList(             key: centerKey,             delegate: SliverChildBuilderDelegate(               (BuildContext context, int index) {                 return Container(                   alignment: Alignment.center,                   color: Colors.blue[200 + bottom[index] % 4 * 100],                   height: 100 + bottom[index] % 4 * 20.0,                   child: Text('Item: ${bottom[index]}'),                 );               },               childCount: bottom.length,             ),           ),         ],       ),     );   } } 

As we see inside CustomScrollView slivers we've used two slivers, SliverAppBar, and SliverList. Both they are Widgets producing RenderSliver objects.

Further reading >>

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter


This free site is ad-supported. Learn more