Master Scrolling in Flutter: Part:1

Cavin Macwan
7 min readApr 2, 2023

--

You’ve been using widgets for almost everything in Flutter. From configuring the layout to achieve scrolling and for directly painting on canvas. That’s why we think everything is a widget in Flutter, right? Well, it’s not right, let’s understand this.

If you look at TextStyles, BoxDecoration and BuildContext, they are not widgets. That kinda feels strange, right? But that raises one another question, what actually a widget is?

Widget

In flutter, we like to say it’s all widgets!!! But that’s not true. So someone from the Flutter team proposed this definition for the widget:

A widget is a discrete block of an App’s UI containing :

  • A static configuration(Stateless and Stateful Widget )
  • Optionally, persistent state (State Object)
  • A render() method

Now, If a widget is just a static configuration, then how does Flutter computes layout and everything? Because the app can change the UI based on some sort of state, but if the widget is immutable then how does it handles changing UI?

Trees in Flutter

In Flutter, there 3 trees named Widget Tree, Element Tree and the Render Object Tree.

Whenever we write widgets, we’re essentially dealing with widget trees. And those widgets create elements, and lastly, these elements create render objects.

But surprisingly, StatelessWidgets and StatefulWidgets which we create all the time don’t render anything😮 because they don’t create render objects. To understand this, let’s look at the types of Widgets.

Types of Widget

  • There are mainly 3 types of Widgets: StatelessWidget, StatefulWidget and RenderObjectWidget and RenderObjectWidget has 2 subtypes named SingleChildRenderObjectWidget and MultiChildRenderObjectWidget
  • Now, If we look at the implementation of StatelessWidget we can see this:
  • Here you can see StatelessWidget overrides a method called createElement, and passes itself into it. It also has the build method that returns a Widget.
  • Same way, if you look at the implementation of StatefulWidget , it has some other methods for creating a state and all along with the build method.
  • But RenderObjectWidget don’t have build methods. Rather, they have createRenderObject method that creates and updates render objects which are displayed on the screen.

Thus, if StatelessWidgets And StatefulWidgets don’t create render objects, then by convention they are not visible on the screen.

Therefore, StatelessWidgets And StatefulWidgets don’t render anything, they are kinda just the middle managers who manage widgets, but only RenderObjectWidgets are drawn on the screen.

And if you want to go deep into this, then you can check the talk by Craig Labenz at Flutter Vikings

But this blog was about scrollables🤔, what is the purpose of these various terminologies and everything? Well, It will make sense once we talk about how flutter handles layout in general😉

How Flutter Handles Layout?

Constraints go down. Sizes go up. Parent sets position.

You may have read this sentence once in your development carrier. Let’s understand this statement. Let’s understand this.

If you look at the docs, you can see:

  • A widget gets its own constraints from its parent.
  • Then the widget goes through its own list of children. One by one, the widget tells its children what their constraints are (which can be different for each child), and then asks each child what size it wants to be.
  • Then, the widget positions its children (horizontally in the x axis, and vertically in the y axis), one by one.
  • And, finally, the widget tells its parent about its own size (within the original constraints, of course)

For the most of the time, we deal with widget tree because

  • We use widgets for displaying stuff like Text and styling something by using DecoratedBox or TextStyles.
  • Widgets like Row, Column and Stack are used to align widgets horizontally, vertically or on top of each other.
  • And other widgets like Padding or Align deal with laying out single-child widgets.

Thus whenever we want to lay out a collection of widgets, we use Column or Row that is capable of laying out multiple Widgets. But When we reach the limit of its constraints, we see an overflow like this:

This will feel kind of strange to the developers who are coming from the web development side. Because for them, scrolling should be enabled by default. But that is not the case with Flutter.

This is the time when Scroll Widgets come into the picture😉

Scrollable Widget

This widget is responsible for the scrolling behavior in Flutter. Whenever you want to make something scrollable, you wrap it with Scrollable Widget.

This scrollable widget implements the interaction model for a scrollable widget, including gesture recognition. But, it does not have an opinion about how the viewport, which actually displays the children, is constructed.

But almost most of the time, we never use Scrollable widgets directly. Instead, we use SingleChildScrollView, ListView or GridView that gives us everything from achieving scrolling functionality to all the scrolling gesture functionalities.

So now you can wrap your Column in SingleChildScrollView and worry about nothing, right?

Well technically, it’s right. But should you do it all the time? Definitely no. Whenever you’re dealing with a small number of lists, you can use SingleChildScrollView , but if your list grows substantially large, you’ll face performance issues in your app.

These performance issues will happen because of all your list will be rendered at once. That means, the content you can’t see on your screen, will be rendered by default.

To overcome this, you can use another scrollable widget like ListView.builder() or GridView.builder() that only renders what is visible on the screen. And that gives you the ability to have virtually an infinite amount of length because it’ll never compromise the performance of your Flutter app.

Slivers

Finally, let’s talk about this thing right now which still many developers think is for only advanced Flutter developers.

For your information, you’ve been using Slivers till this date without knowing. Yes, you heard it right😉 ListView , GridView and other Scrollable widgets implement Slivers under the hood without you having to deal with it directly.

Because most of the time, you don’t need to directly deal with it. But there can be scenarios where you want to scroll ListView and GridView together or you want to achieve some custom scrolling effects which would be otherwise won’t be possible with ListView or GridView. At that time, you can use Slivers explicitly.

But what slivers actually are? If you look at the docs of Slivers you can see the following statement:

A sliver is a portion of a scrollable area that you can define to behave in a special way.

As we’ve seen previously, a widget gets a set of constraints from its parent to know how big or small a child should be. But with Slivers, things are different.

A sliver doesn’t have BoxConstraints but rather they have SliverConstraints which has different parameters from BoxConstraints because in that we need to know about the direction of scrolling and the axis of scrolling and lots of other parameters related to it.

And to render silvers, you can use CustomScrollView that takes a list of Slivers and renders it onto the screen.

I hope you learned something new from this blog today. If you didn’t understand any of the part or have any doubts, then you can ask me in the comments, or on my LinkedIn and Twitter.

In the next part, we’re gonna see what are the types of slivers and how you can utilize them in order to achieve custom scrolling effects and improve the performance of your Flutter app.

Till then, you can look at some resources I took inspiration from:

Keep clapping 👏 (you can appreciate it by clapping 50 times)

You can connect with me on LinkedIn, Twitter and don’t forget to follow me here for more updates.

Note: We are building a community for Flutter Developers where anyone can share their ideas or content, ask doubts about Flutter/other tech and collaborate with each other. If you are interested in being part of this then you can join our discord server by this link: https://7span.in/club

--

--

Cavin Macwan

Passionate mobile developer. One thing I like more than learning new things: sharing them #FlutterDev| Developer @7Span | Contributor