Slivers in Flutter - Efficient and Fancy Scrolling Experience

Learn one of the scariest topics in Flutter - what is sliver and how to make use of it to build an elegant scroll view

thecodexhub
Towards Dev

--

Photo by Nathana Rebouças on Unsplash

Widgets are the foundation of Flutter’s layout system. Almost everything in Flutter is a widget, including layout models. Widgets are what you see in a Flutter app as images, icons, and text. Things you can’t see, such as the rows, columns, and grids that arrange, constrain, and align the visible widgets, are also widgets.

The RenderObject class is the core of the rendering library and it handles the visual elements tree and specifies the layout, painting, and composting procedures. RenderObject doesn’t have any specific layout protocol, and it also doesn’t define a child model. The implementers of RenderObject class (such as RenderBox, RenderSliver, RenderAbstractViewport, and RenderView) introduce layout systems and child models.

Most of the RenderObjects are RenderBox.

The RenderBox has its cartesian coordinate system and box constraints that determine the minimum and maximum value of the height and width of its child. These values are then used to find out the size of the child.

Common examples of RenderBox are Container, SizedBox, etc. They follow the RenderBox protocol to describe and paint the layout model based on the Cartesian space and box constraints.

What are Slivers?

While RenderBox is ideal for rendering objects in cartesian coordinates, they are not a good fit for scrolling widgets. For scrolling, there is Sliver protocol. The render objects that implement scroll effects in viewports use RenderSliver as their base class.

Sliver is a segment of the viewport’s content that is laid out to cover up the viewport. Slivers participate in sliver protocol.

In the case of box protocol, the RenderBox gets the box constraints and determines the child's size. Similarly, in sliver protocol, during the layout mechanism, the sliver gets a SliverConstraints and calculates the corresponding SliverGeometry that tells where to fit in the sliver in the viewport.

Need for Slivers: Advantages

Under the hood, slivers are used to implement all of the scrollable views you use, including ListView and GridView. Slivers can be compared to a lower-level interface that offers more precise control over the implementation of scrollable areas.

RenderSliver lets you render child widgets lazily or render only the visible segment of the screen. Additionally, RenderSliver provides a better experience when you need to scroll a list of items and a grid of items all together as a single unit or create a collapsible header. It makes the overall scrolling effect of large lists effective and efficient.

How to work with Slivers

To create a scroll view with custom scroll effects using slivers, we need to use the CustomScrollView widget. Slivers can be directly supplied to a CustomScrollView to produce a variety of scrolling effects, including lists, grids, and collapsible headers.

Scrollable app bar: SliverAppBar

SliverAppBar is a material-designed app bar that can be integrated with CustomScrollView. Typically, SliverAppBars are used as the first child of the CustomScrollView that integrates the app bar with the scroll view so that the app bar can scroll, and change heights depending upon the scroll offset.

If the flexibleSpace is defined, it is rendered behind the toolbar and the bottom widget. And its height can be determined from the specified expandedHeight.

Pinned, Floating, and Snap app bar

Also, there are some other cool properties of the SliverAppBar.

If the pinned is set to true, the app bar gets pinned and remains visible at the top of the scroll view.

If the floating is set to true, the app bar gets visible as soon as the user starts scrolling backward. Otherwise, if floating is false, the user has to go to the top to reveal the app bar.

And if the snap is set to true, the app bar will be fully expanded when you scroll back. Remember, the snap can only be set to true if the floating is true.

When pinned is true and floating, snap are false
When floating is true but pinned and snap are false
When floating and snap are true, and pinned is false

All about SliverList

The SliverList widget is a sliver that renders multiple children in a linear way along the main axis. While rendering the list, the elements, states, and the rendering of the already visible render objects in the viewport will be laid out lazily based on an already existing widget (such as SliverChildListDelegate) or lazily-provided one (such as SliverChildBuilderDelegate).

Alternatively, we can also use the SliverFixedExtentList, which is more efficient for children with the same extent in the main axis.

SliverList with SliverAppBar having all pinned, floating and snap set to true

Grid layout with SliverGrid

The SliverGrid widget lays out its children in an arbitrary two-dimensional arrangement based on the gridDelegate. Similarly, as SliverList, while rendering, the render objects in the viewport will be laid out either by specifying the children list (using SliverChildListDelegate) or by creating them lazily (using SliverChildBuilderDelegate).

SliverGrid along with SliverList

Sliver with single widget: SliverToBoxAdapter

The SliverToBoxAdapter is a sliver widget that holds one single box widget.

Slivers are special purpose widgets that can be coupled with a CustomScrollView to produce a fancy scrolling experience. A SliverToBoxAdapter is a straightforward sliver that builds a link to a common box-based widget.

Consider using SliverList, SliverFixedExtentList, or SliverGrid, which are more efficient because they instantiate only those children that are visible through the scroll view’s viewport, rather than multiple SliverToBoxAdapter widgets to display multiple box widgets in a CustomScrollView.

SliverToBoxAdapter with a single box object — Container

SliverFillRemaining: Fill the remaining viewport

A sliver that occupies the remaining space in the viewport with a single box child is the SliverFillRemaining widget. The child will be sized to fill the cross-axis extent but the size in the main axis will be determined conditionally using the hasScrollBody property.

The hasScrollBody indicates whether the child of the SliverFillRemaining sliver is scrollable. If the value is true (also default is set to true), the child will be sized to fill the maximum main axis extent. And if the property is set to false, the child’s size will be taken into account to determine the extent to which it should fill the space.

SliverFillRemaining widget

Custom reusable headers with SliverPersistentHeader

SliverAppBar, under the hood, is a SliverPersistentHeader widget. While the SliverAppBar is customizable, sometimes you’ll need more customization and you’ll find most of the properties of the SliverAppBar in the SliverPersistentHeader along with some more customization options.

We’ll use the SliverPersistentHeader to make a sophisticated, persistent subheader that expands when you scroll down but maintains a minimum height when you scroll up.

SliverPersistentHeader requires a delegate class that extends the abstract class SliverPersistentHeaderDelegate. You should override the shouldRebuild to rebuild whenever one of these three properties changes - minHeight, maxHeight, and child.

And now as we have our custom SliverPersistentHeaderDelegate, we can complete making our SliverPersistentHeader.

SliverPersistentHeader widget

Complete project with source code

Check out the complete source code for this application via the following link.

Conclusion

In this article, we have covered how to use slivers to make the scrolling experience much more elegant and sophisticated in Flutter. The background of the scrolling widgets, render objects, box protocol, and sliver protocol have also been covered in this article.

We have explored some of the in-built sliver widgets including SliverAppBar, SliverList, SliverGrid, SliverToBoxAdapter, and SliverFillRemaining to create fancy looking UI. Also, we have looked into SliverPersistentHeader to create a custom collapsible subheader.

If you have any queries or suggestions or questions, dive into the comments sections. Alternatively, you can reach out to me using Instagram, Twitter, LinkedIn, or Email.

Please remember to applaud if this article was helpful and taught you something new. You know you can clap 50 times 🚀using that clap button. Give it a shot.😅

That’s it. Hope it helps!

--

--

Passionate Flutter Developer from INDIA || Technical Content Creator || Instagram: @thecodexhub