There’s A Gist For That

I’ve composed a composite example, ListViewScrollController.dart, including all three features illustrated above. Again, merely a few capabilities made available to you using a ScrollController with your ListView.

Where Are You?

From left-to-right, we’ll review each example. In the first one, you see that scrolling up to the top of the listing will change the app’s title to ‘reached the top.’ This requires a ScrollController object being provided to the ListView.builder and assigned a ‘listener.’ In the example’s initState() function, the ScrollController is instantiated and assigned such a listener.

This listener has the means to determine where at any point in time we’re currently positioned in the scrollable list using the ScrollController property, offset. The offset is a double value indicating the ‘accumulative distance’ in ‘logical pixels’ from the beginning of the scrollable listing. The beginning of the listing has an offset of 0.0. Once instantiated, the ScrollController object is taken in by the ListView’s named parameter, controller.

Logical pixels are roughly the same visual size across devices while Physical pixels are the size of the actual hardware pixels on the device. Logical pixels are to be device-independent and resolution-independent pixels.

The Offset From the Start

In most cases, ListView’s starts with an offset of 0.0. In other words, start from the beginning of the scrollable listing. Of course, with the ScrollController object, you can start wherever you like. Its constructor will accommodate that with the named parameter, initialScrollOffset. Note, it defaults with 0.0.

Reach The Top

Now back to our example. Looking at the Listener routine defined and introduced to the ListView by the addListener() function, we see the ScrollController knows the ‘start’ of the scrollable list using the value from, con.position.minScrollExtent. You guessed it — its value would be 0.0. And so, if the ‘current offset’ (con.offset) is 0.0, you’ve reached the start of the list. The title is thus changed appropriately.

Automate The Scrolling

The next example involves scrolling automatically with the use of a ScrollController object. In our example, a little automation is used.

As you see in the screenshot above, we define a function called, rowButtons(), that returns the widget containing the ‘up’ and ‘down’ buttons presented in the second example. Also in the code is the ScrollController function, animatTo(), that’s responsible for the animation. The first parameter in the function indicates the offset to ‘move to’ from the current offset position in the scrollable list. In this example, we merely move by ‘the width’ of a listed child widget, itemSize. You can see how that’s done by ‘adding’ or ‘subtracting’ the specified size.

The curve parameter describes the ‘how’ the animation moves: if it speeds up as it moves and or slows down as it moves. In this example, the animation is performed at a constant speed with the option, Curves.linear. It’s the parameter, duration, that dictates the actual speed as it sets the time it takes to complete the animation.

Note, the function, jumpTo(), commented out in the screenshot moves the scrollable listing with a flash and without the animation. Not nearly as neat.

As you see in the screenshot above, the function, rowButtons(), is placed above the scrollable list produced by the ListView.builder constructor. A new parameter, itemExtent, is introduced in the constructor, and it specifies ‘the width’ of each ‘child’ widget listed in the scrollable list. It’s described as ‘ the size of the child along the main axis’. In other words, the width either vertically or horizontally depending on if the ListView parameter, scrollDirection, is set, Axis.vertical, or Axis.horizontal.

IIt’s said in the documentation it would mean better performance to always specify the ‘itemExtent’ property when making your ListViews as this then relieves Flutter in having to compute ‘the width’ itself every time.

Dispose Of The Controller

Don’t forget to dispose of the ScrollController when you’re done. They take up resources and should be cleaned up when no longer in use.

Primary

The next parameter is called, primary. It’s used to indicate whether this is the primary scroll view associated with the parent PrimaryScrollController. This means there must be no ScrollController parameter if primary is set to true.

When this is true, the scroll view is scrollable even if it does not have sufficient content to actually scroll. Otherwise, by default, the user can only scroll the view if it has sufficient content. On iOS, if set true, this also identifies the scroll view that will scroll to top in response to a ‘tap’ in the status bar.