Slivers in Flutter: Getting Started
In this article you’ll learn about Slivers in Flutter, how they work, and use them to make a beautifully designed app for recipes. By Michael Malak.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Slivers in Flutter: Getting Started
25 mins
- Getting Started
- Understanding Slivers
- Displaying Recipe List
- SliverFixedExtentList and SliverList
- Building a Scrollable App Bar
- Reusing SliverAppBar
- Inserting a Footer to CustomScrollView
- Adjusting the Layout
- Controlling the SliverGrid Layout
- Adding the Ingredients Grid
- Adding the Numbers Grid
- Implementing SliverPersistentHeaderDelegate
- Customizing a Subheader With SliverPersistentHeader
- Where to Go From Here?
SliverFixedExtentList and SliverList
As you may have guessed from their names, SliverList is more generic and flexible compared to SliverFixedExtentList. The latter assumes a fixed extent for its children, while the former doesn’t specify an extent and renders the children widgets with their constraints.
If you wanted to rewrite the recipe list using SliverList instead of SliverFixedExtentList you could do so by wrapping RecipeItem with a height constraint. No need to make this change in your code, but it’s here for your reference:
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => SizedBox(
height: 110,
child: Padding(
padding: const EdgeInsets.only(bottom: 20),
child: RecipeItem(recipes[index])),
),
childCount: recipes.length,
),
),
Which of the two, SliverList and SliverFixedExtentList, do you think is more efficient?
[spoiler title="SliverList vs SliverFixedExtentList"]
SliverFixedExtentList is highly more efficient than SliverList as it doesn’t need to calculate the extent of its children dynamically. Try to use SliverListExtentList as possible, and only resort to SliverList if you need to support children of varying or dynamic extents.
[/spoiler]
Time for you to extend Reciperlich with a nice scrollable App Bar.
Building a Scrollable App Bar
Now that you have a list of recipes, you need to add a cool scrollable app bar. Developers commonly use slivers to customize app bars with behavior different from Flutter’s default AppBar widget.
Since you’ll reuse the same app bar in the app’s two pages, create a new AppBarWidget in the shared folder.
In lib/shared_widgets, add a new file named app_bar_widget.dart and add the following code to it:
import 'package:flutter/material.dart';
import '../constants/colors.dart';
import 'image_with_top_shadow_widget.dart';
class AppBarWidget extends StatelessWidget {
// 1
final String text;
final String imagePath;
final bool centerTitle;
const AppBarWidget({
Key key,
@required this.text,
@required this.imagePath,
this.centerTitle = false,
}) : assert(text != null),
assert(imagePath != null),
super(key: key);
@override
Widget build(BuildContext context) {
// 2
return SliverAppBar(
title: Text(
text,
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
backgroundColor: AppColors.navy,
centerTitle: centerTitle,
// 3
expandedHeight: 200.0,
// 4
pinned: true,
elevation: 0,
// 5
flexibleSpace: FlexibleSpaceBar(
background: ImageWithTopShadowWidget(imagePath),
),
);
}
}
Here’s a step-by-step code breakdown:
-
AppBarWidgettakes two mandatory properties: the title text and image path with. It also takes a Boolean property which decides if it should center the text title, which default tofalse. -
SliverAppBaris a scrollable app bar. You give it the same properties asAppBaras well as properties that define the scrollability behavior. - You provide the
expandedHeightto set the app bar’s size when it’s fully expanded. By setting the value here, you make the app bar scrollable. - When you set
pinnedtotrue, you let the app bar remain visible at the start of the scroll view. - You add an image with a shadow widget stacked behind the toolbar and the tab bar. By adding it to
FlexibleSpaceBar, you set its height to the same as the app bar’s overall height.
SliverAppBar has three Booleans in its configuration. When you change them, you alter the behavior of the app bar when scrolling:
-
pinned: When set totrue, the app bar will remain visible as the user scrolls. -
floating: By setting it totrue, you make the app bar visible as soon as the user scrolls towards the app bar. Otherwise, they’ll need to scroll near the top of the scroll view to reveal the app bar. -
snap: Whentrue, the app bar will fully expand as you scroll, which is helpful when you have a text field in the app bar.
Check out this great interactive demo from Flutter documentation for these three Booleans.
Now that you added the shared AppBarWidget, you’ll add it to the recipe list page.
Reusing SliverAppBar
Back in lib/pages/recipe_list/recipe_list_page.dart, add an import to AppBarWidget at the top of the file:
import '../../constants/app_image_paths.dart';
import '../../shared_widgets/app_bar_widget.dart';
Now, replace // TODO: Add a cool AppBar with:
const AppBarWidget(
text: 'Reciperlich',
imagePath: AppImagePaths.mainImage,
centerTitle: true,
),
Here’s what you just did:
- Instead of adding
AppBarWidgetto theappBarinScaffold, you inserted it directly as a child inCustomListViewabove the recipe list, since it is a sliver. - Then, you used
AppImagePathsto provide theAppBarWidgetwith the main image path.
Build and run. You’ll see your recipe list page in action!
Now, you’ll add AppBarWidget to the other page, RecipePage.
Go to lib/pages/recipe/recipe_page.dart and, at the top of the file, add:
import '../../shared_widgets/app_bar_widget.dart';
Next, replace // TODO: add an AppBarWidget with:
AppBarWidget(
text: recipe.title,
imagePath: recipe.mainImagePath,
),
Build and run to ensure the AppBarWidget works. Then, click any recipe item. When RecipePage opens, you’ll see the app bar behaves the same on both pages.

Inserting a Footer to CustomScrollView
Now you have two slivers inside CustomScrollView in RecipeListPage. They animate together when you scroll.
But what if you want to add a widget that produces a RenderBox, like a SizedBox or a Container? And what if you want to add it to CustomScrollView and scroll it with the other slivers even though it’s not a sliver?
No worries! Flutter’s got your back. This is the perfect situation to use SliverToBoxAdapter to convert boxes to slivers.
You’ll now add a footer to the CustomScrollView in RecipeListPage. Go over to lib/pages/recipe_list/widgets/footer_widget.dart, where you’ll find FooterWidget. It returns a Column widget.
You’ll use it as a footer for RecipeListPage.
Go back to lib/pages/recipe_list/recipe_list_page.dart. Import FooterWidget at the top of the file:
import 'widgets/footer_widget.dart';
Then, add the following at the end of the slivers argument, right under SliverFixedExtentList inside CustomScrollView:
const SliverToBoxAdapter(
child: FooterWidget(),
),
Build and run. See the footer when you scroll at the end. Isn’t it lovely?
Adjusting the Layout
The recipe list needs some padding. However, Flutter’s Padding widget doesn’t take slivers. You’ll need widgets like Padding, SafeArea, Opacity and Visibility but for slivers.
Once again, Flutter comes to the rescue! You’ll use classes that give the same functionality but take slivers: SliverPadding, SliverOpacity, SliverOpacity and SliverVisibility.
RenderSliver always start with Sliver. Hence, you have SliverAppBar, SliverGrid, SliverList and SliverPadding. This usually comes in handy when you use autocomplete in your IDE.Wrap SliverFixedExtentList like this:
SliverPadding(
padding: const EdgeInsets.all(20),
sliver: SliverFixedExtentList(...),
),
Build and run. See that you’ve adjusted the padding.


