Flutter - SliverAppBar Example Draft

This tutorial shows you some examples how to create SliverAppBar in Flutter and how you can customize it with the list of available options. This include how to create shrinking header and adjust the scroll effects.

SliverAppBar is a kind of app bar in Flutter that's compatible with CustomScrollView. SliverAppBar is usually used as the first child of CustomScrollView's slivers. This widget allows you to easily create an app bar with various scrolling efects.

A very basic SliverAppBar consisting of title only without any effect can be created with this code:

  slivers: <Widget>[
    SliverAppBar(
      title: Text("SliverAppBar Title"),
    )
  ],

Below are some examples of SliverAppBar with various scroll effects.

Shrinking Header

In the last few years, maybe you have seen some apps, either web or mobile, which have header section that will be shrinked when the user scrolls down the page. It can also be done using SliverAppBar. What we need to set is expandedHeight and flexibleSpace. expandedHeight, as the name suggests, is the height of the app bar when it's fully expanded. In flexibleSpace, you can pass a widget that will be rendered when the app bar is expanded, typically a FlexibleSpaceBar.

  SliverAppBar(
    title: Text("SliverAppBar Title"),
    expandedHeight: 220.0,
    flexibleSpace: FlexibleSpaceBar(
        centerTitle: true,
        title: Text('Title',
            style: TextStyle(
              color: Colors.white,
              fontSize: 16.0,
            )),
        background: Image.network(
          'https://images.pexels.com/photos/443356/pexels-photo-443356.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
          fit: BoxFit.cover,
        )
    ),
  ),

To modify scrolling behavior, there are three properties you need to control: pinned, floating, and snap.

If pinned is true, the app bar will always be visible at the top of the scroll view. In other word, the app bar will be sticky at the top. Otherwise, the app bar will disappear when you scroll down.

The second property, floating, makes it possible for the app bar to be displayed at the top of the screen. If you set it to false, you have to scroll up until you reach the top element under the app bar in order to make the app bar expanded again. If you set it to true, just scroll up a little bit and the app bar will be expanded again. You can see the comparison below.

pinned: true, floating: false, snap: false

Flutter SliverAppBar - pinned: true, floating: false, snap: false

 

 

pinned: true, floating: true, snap: false

Flutter SliverAppBar - pinned: true, floating: true, snap: false

The last property is snap which can only be used if pinned and floating are both set to true. If you set snap to true, then try to scroll down when the app bar is not expanded, you'll see that the app bar will be snapped into the view.

pinned: true, floating: false, snap: true

Flutter SliverAppBar - pinned: true, floating: false, snap: true

Leading Widget

Another thing you can add is a leading Widget. It's a small area that's rendered on the top left before the title. Usually it's used to render logo or drawer icon.

  SliverAppBar(
    leading: IconButton(
      icon: Icon(Icons.filter_1),
      onPressed: () {
        // Do something
      }
    ),
    ...
  ),

Options

Below is the list of available options you can pass in the constructor.

Option Description
Key key The widget's key.
Widget leading Widget to be displayed before title.
bool automaticallyImplyLeading Whether to imply the leading widget if it's null.
Widget title The primary widget displayed in the appbar. Usually a Text.
List<Widget> actions Widgets to be displayed after title.
Widget flexibleSpace Widget stacked behind the toolbar and the tab bar whose weight is the same as app bar's.
PreferredSizeWidget bottom Widget that appears across the bottom of the appbar
double elevation Z-coordinate of the app bar which affects the shadow
bool forceElevated Whether to show shadow even if the content is not scrolled under the app bar.
Color backgroundColor Color for app bar's material.
Brightness brightness Brightness for app bar's material.
IconThemeData iconTheme Color, opacity, and size of app bar ions.
IconThemeData actionIconTheme Color, opacity, and size of trailing app bar ions.
TextTheme textTheme Typographic styles.
bool floating Whether this app bar is being displayed at the top of the screen.
bool centerTitle Whether to place the title on center.
double titleSpacing Spacing around title content.
double expandedHeight Size of the app when it's fully expanded.
bool pinned Whether to make app bar always visible at the top of the scroll view.
bool snap If snap and floating are true then the floating app bar will snap into view.

Full Code

  import 'package:flutter/material.dart';
  
  void main() => runApp(SilverAppBarExample());
  
  class SilverAppBarExample extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        home: Scaffold(
          body: CustomScrollView(
            slivers: <Widget>[
              SliverAppBar(
                leading: IconButton(
                  icon: Icon(Icons.filter_1),
                  onPressed: () {
                    // Do something
                  }
                ),
                expandedHeight: 220.0,
                floating: true,
                pinned: true,
                snap: true,
                elevation: 50,
                backgroundColor: Colors.pink,
                flexibleSpace: FlexibleSpaceBar(
                    centerTitle: true,
                    title: Text('Title',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 16.0,
                        )),
                    background: Image.network(
                      'https://images.pexels.com/photos/443356/pexels-photo-443356.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
                      fit: BoxFit.cover,
                    )
                ),
              ),
              new SliverList(
                  delegate: new SliverChildListDelegate(_buildList(50))
              ),
            ],
          ),
        ),
      );
    }
  
    List _buildList(int count) {
      List<Widget> listItems = List();
  
      for (int i = 0; i < count; i++) {
        listItems.add(new Padding(padding: new EdgeInsets.all(20.0),
            child: new Text(
                'Item ${i.toString()}',
                style: new TextStyle(fontSize: 25.0)
            )
        ));
      }
  
      return listItems;
    }
  }