Flutter Scrollbar Interactive

In our previous section we’ve seen how we can create a Scrollbar. We have also seen how we can read about other Scrolling Widgets. A Scrollbar always belongs to the Scrolling widgets category. And there are more you may have interest in.

At the end of this post we’ll provide you a list of other Scrolling Widgets.

When we say that a Scrollbar is interactive, actually what does that mean?

Let’s try to understand that concept first. Why so? Because we’ve seen in our previous section that a Scrollbar thumb can be dragged along the main axis of the ScrollView to change the ScrollPosition.

If we tap along the track where the Scrollbar thumb operates, it will trigger a ScrollIncrementType.page based on the relative position to the thumb. In addition, a Scrollbar, due to its interactive nature, can use the PrimaryScrollController if a controller is not set.

Moreover, if we can provide a unique ScrollController to each Scrollable, we can prevent multiple ScrollPositions being attached to the PrimaryScrollController.

In our previous Scrollbar example we’ve seen how a Scrollbar’s ScrollView.scrollDirection of Axis.vertical automatically attaches its ScrollPosition to the PrimaryScrollController. It takes place because we’ve not provided a ScrollController.

Scrollbar in flutter
Scrollbar in flutter

What is the role of ScrollController in a Scrollbar?

When we say a Scrollbar is interactive, it directly has a link to the State of the object. In fact, to be more precise, we can say that each scroll controller is stored as member variable in State objects.

Why?

Because they can be reused in each State.build. Therefore, a ScrollController actually controls a scrollable widget.

As a result, we can subsequently confirm that a ScrollController creates a ScrollPosition to manage the state specific to an individual Scrollable widget. Consequently, a ScrollController always notifies its listeners whenever a user scrolls and the ScrollPosition changes.

To understand this concept let’s see the screenshots firstly.

Scrollbar controller sample one
Scrollbar controller sample one

The above image shows us a column and inside that column we have two scrollable widgets.

Watch the first Scrollbar code.

Scrollbar(
              isAlwaysShown: true,
              controller: _controllerOne,
              child: ListView.builder(
                controller: _controllerOne,
                itemCount: 20,
                itemBuilder: (BuildContext context, int index) => Text(
                  'item $index',
                  style: const TextStyle(
                    color: Colors.red,
                    fontSize: 40.0,
                    fontFamily: 'Allison',
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),

The parameter isAlwaysShown is true. That means the Scrollbar thumb will always show. However, in the above screenshot the second Scrollbar thumb also is being displayed. It’s because we were dragging that so it showed itself.

isAlwaysShown: true,

Although in the next screenshot, the second Scrollbar thumb is not being displayed as it has faded out.

Scrollbar controller sample two
Scrollbar controller sample two

It happened because the parameter isAlwaysShown is not true anymore in the second Scrollbar.

Let’s see the full code so that we can get an idea how a ScrollController acts as a Listenable. And, how it updates the state of the scroll position.

In addition to that it also manages state by maintaining the ScrollPosition.

import 'package:flutter/material.dart';

/// This is the main application widget.
class ScrollbarControllerSample extends StatelessWidget {
  const ScrollbarControllerSample({Key? key}) : super(key: key);

  static const String _title = 'Scrollbar Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const Center(
          child: ScrollbarControllerSampleHome(),
        ),
      ),
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class ScrollbarControllerSampleHome extends StatefulWidget {
  const ScrollbarControllerSampleHome({Key? key}) : super(key: key);

  @override
  State<ScrollbarControllerSampleHome> createState() =>
      _ScrollbarControllerSampleHomeState();
}

/// This is the private State class that goes with ScrollbarControllerSampleHome.
class _ScrollbarControllerSampleHomeState
    extends State<ScrollbarControllerSampleHome> {
  // Generate a dummy list
  //final myProducts = List<String>.generate(10, (i) => 'Product $i');
  final ScrollController _controllerOne = ScrollController();
  final ScrollController _controllerTwo = ScrollController();
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(30),
      child: Column(
        children: <Widget>[
          SizedBox(
            height: 200,
            child: Scrollbar(
              isAlwaysShown: true,
              controller: _controllerOne,
              child: ListView.builder(
                controller: _controllerOne,
                itemCount: 20,
                itemBuilder: (BuildContext context, int index) => Text(
                  'item $index',
                  style: const TextStyle(
                    color: Colors.red,
                    fontSize: 40.0,
                    fontFamily: 'Allison',
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
          ),
          const SizedBox(
            height: 20,
          ),
          SizedBox(
            height: 200,
            child: Scrollbar(
              controller: _controllerTwo,
              child: ListView.builder(
                controller: _controllerTwo,
                itemCount: 20,
                itemBuilder: (BuildContext context, int index) => Text(
                  'list 2 item $index',
                  style: const TextStyle(
                    color: Colors.blue,
                    fontSize: 40.0,
                    fontFamily: 'Allison',
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Although we have used ListView.builder constructor as scrollable widgets inside the Scrollbar, we could have used ListViewGridView, or CustomScrollView.

To sum up, when we say that flutter Scrollbar is interactive, it actually means change of ScrollPosition attached to the controller. When we pass a ScrollController, it implements Scrollbar dragging. When we drag, the Scrollbar thumb updates its position.

By the way, you may want to take a look at the other Scrolling Widgets, before we close down further reading on this topic. We have a list below.

What is ListView Flutter? How do I use ListView in Flutter?

How do I use SingleChildScrollView in flutter?

What is GridView and how do you centre a GridView item in Flutter?

What is GridView builder in Flutter?

What is the grid view in Flutter?

What is GridView count in flutter?

What is GridView.extent in Flutter?

How do I make my collapsing toolbar flutter?

What is SliverGrid in flutter?

How to use CustomScrollView in Flutter?

How to use NestedScrollView in flutter?

How to use PageView in Flutter

What is PageView builder in flutter?

What is PageView custom in flutter?

How to use DraggableScrollableSheet

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

2 responses to “Flutter Scrollbar Interactive”

  1. […] Flutter Scrollbar Interactive […]

  2. […] Flutter Scrollbar Interactive […]

Leave a Reply