skip to Main Content

I think that I have always used RawScrollbar rather than Scrollbar and I presume that that is because it is more configurable. Why is it that in using RawScrollbar it appears necessary to specify a ScrollController while using Scrollbar it is not necessary to specify a controller? I presume that Scrollbar uses the default ScrollController, but I have found no way to use that with RawScrollbar. Not that it makes a massive difference, but it does require that the ScrollController must be defined and must be disposed of, while I presume that Flutter handles the disposal of the default ScrollController. I did see some mention that there is a difference with desktop and perhaps it stated that there is no default ScrollController with desktop. If that is the case, I presume that one may as well create a ScrollController and dispose it.

So, the question is – Can I use the default ScrollController with RawScrollbar and if so, how? And if so, is it worth using the default ScrollController if it cannot be used with desktop?

2

Answers


  1. Chosen as BEST ANSWER

    Some more testing revealed the following:

    EXAMPLE

    Running the following code in debug results in the following error:

        return Expanded(
            child: RawScrollbar(
                thumbVisibility: true,
                thumbColor: Colors.blue[600],
                shape: const StadiumBorder(),
                thickness: 15,
                scrollbarOrientation: ScrollbarOrientation.left,
                padding: EdgeInsets.only(left: 2),
                //controller: PrimaryScrollController.of(context),
                ////controller: _wScrollController,
                minThumbLength: 100,
                child: ListView.builder(
                    shrinkWrap: true,
                    //controller: PrimaryScrollController.of(context),
                    ////controller: _wScrollController,
                    primary: false,
                    itemCount: _lmNutrientsByName.length + 1,
                    itemBuilder: (context, iNdxRow) {
    
    

    ----------- Debug output ------- ══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════ The following assertion was thrown during a scheduler callback: The Scrollbar's ScrollController has no ScrollPosition attached. A Scrollbar cannot be painted without a ScrollPosition. The Scrollbar attempted to use the PrimaryScrollController. This ScrollController should be associated with the ScrollView that the Scrollbar is being applied to.When ScrollView.scrollDirection is Axis.vertical on mobile platforms will automatically use the PrimaryScrollController if the user has not provided a ScrollController. To use the PrimaryScrollController explicitly, set ScrollView.primary to true for the Scrollable widget.

    When the exception was thrown, this was the stack: #0 RawScrollbarState._debugCheckHasValidScrollPosition. (package:flutter/src/widgets/scrollbar.dart:1459:9) #1 RawScrollbarState._debugCheckHasValidScrollPosition (package:flutter/src/widgets/scrollbar.dart:1484:6) #2 RawScrollbarState._debugScheduleCheckHasValidScrollPosition. (package:flutter/src/widgets/scrollbar.dart:1415:14) #3 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1386:15) #4 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1322:11) #5 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1169:5) #6 _invoke (dart:ui/hooks.dart:312:13) #7 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:399:5) #8 _drawFrame (dart:ui/hooks.dart:283:31)


    The situation with regards to example and the resulting error appears to me to be that the error message “The Scrollbar's ScrollController has no ScrollPosition attached.” “A Scrollbar cannot be painted without a ScrollPosition.”

    The actual error appears to me to be that there is no ScrollController for the Scrollable widget because “primary” was set to false. In my opinion the error message is not descriptive enough, and in addition “primary” would be better named “primaryScrollController” to make it more explicit. It is probably too late for that to happen. Perhaps ‘primary’ could be made redundant and default to the PrimaryScrollController for a scrollable Widget if no ScrollController is specified, however there may be more to it than that and there may be cases where a ScrollController is not wanted.

    With regards to desktop, the Flutter documentation states :

    “Default PrimaryScrollController on Desktop “The PrimaryScrollController API has been updated to no longer automatically attach to vertical ScrollViews on desktop platforms.” … etc.


  2. No, you cannot directly use the default ScrollController with the RawScrollbar. You need to create and manage your own ScrollController instance. It’s worth creating your own ScrollController for consistency and control, especially if you’re targeting desktop platforms.

    To create your ScrollController, you can instantiate it within your Flutter widget’s state class. Here’s a basic example of how to do it:

    import 'package:flutter/material.dart';
    
    class MyScrollableWidget extends StatefulWidget {
      @override
      _MyScrollableWidgetState createState() => _MyScrollableWidgetState();
    }
    
    class _MyScrollableWidgetState extends State<MyScrollableWidget> {
      // Create a ScrollController instance
      ScrollController _scrollController = ScrollController();
    
      @override
      void dispose() {
        // Dispose the ScrollController when the widget is disposed
        _scrollController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: RawScrollbar(
            controller: _scrollController, // Use the created ScrollController
            isAlwaysShown: true,
            child: ListView.builder(
              controller: _scrollController, 
              itemCount: 100,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text('Item $index'),
                );
              },
            ),
          ),
        );
      }
    }
    

    In this example, we create a _scrollController instance within the state class of MyScrollableWidget. We dispose of the controller in the dispose method to ensure proper cleanup when the widget is removed from the widget tree. Then, we utilize this ScrollController instance by passing it to both the RawScrollbar widget and the ListView.builder, ensuring synchronization between scrollbar and list view scrolling.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search