Flutter ScrollControllers '_positions.isNotEmpty' error - even when controllers are attached

28 views Asked by At

I have a child widget, with three Text() subwidgets that each need a scroll controller. Some of the Text() subwidgets may not exceed the width of their parent, but for those that do I would like them to scroll so that the user can see the full string.

This child widget is built using a listview.builder. I do not attach a controller using the listview.builder controller named argument - as I need to have one controller per text widget in each child as ScrollControllers are not multi-use. I use timers to trigger the scrolling behaviour and also to return the text to its start position.

Im having sporadic errors in flutter when I scroll, because the ScrollControllers dont appear to be being attached correctly. I dont want to just catch-and-ignore, id like to see what error im making in specification of the scroll controllers.

Visually, when a scroll down the listview I can still see the scrolling behaviour, I just get a stream of errors like this:

E/flutter (32685): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: 'package:flutter/src/widgets/scroll_controller.dart': Failed assertion: line 199 pos 12: '_positions.isNotEmpty': ScrollController not attached to any scroll views.
E/flutter (32685): #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)
E/flutter (32685): #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
E/flutter (32685): #2      ScrollController.animateTo (package:flutter/src/widgets/scroll_controller.dart:199:12)
E/flutter (32685): #3      _TenderTileState._scrollText.<anonymous closure>.<anonymous closure> (package:WiseBuy/UI/tiles/tender_tile.dart:119:28)
E/flutter (32685): #4      new Future.delayed.<anonymous closure> (dart:async/future.dart:427:39)
E/flutter (32685): #5      Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
E/flutter (32685): #6      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
E/flutter (32685): #7      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
E/flutter (32685): #8      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12)
E/flutter (32685): 

Scroll Controller Instantiation

class Tile extends ConsumerStatefulWidget {
  final ScrollController scrollControllerSummary = ScrollController();
  final ScrollController scrollControllerNote = ScrollController();
  final ScrollController scrollControllerInsight = ScrollController();
  // other Tile variables
}

Each Tile Widgets init(), dispose() and timer trigger

@override
  void initState() {
    super.initState();

    SchedulerBinding.instance.addPostFrameCallback((_) {
      //   define the auto-scroll timers for auto-scrolling views!
      _scrollTimer = Timer.periodic(const Duration(seconds: 2), (timer) {
        _scrollText(widget.scrollControllerSummary);
        _scrollText(widget.scrollControllerNote);
        _scrollText(widget.scrollControllerInsight);
      });
    });
  }

  @override
  void dispose() {
    _scrollTimer?.cancel();
    widget.scrollControllerSummary.dispose();
    widget.scrollControllerNote.dispose();
    widget.scrollControllerInsight.dispose();

    super.dispose();
  }

  void _scrollText(ScrollController scrollController) async {
    if (scrollController.hasClients) {
      await scrollController.animateTo(
        scrollController.position.maxScrollExtent,
        duration: const Duration(seconds: 3),
        curve: Curves.ease,
      ).then((_) {
        // Delay before resetting the scroll position
        Future.delayed(const Duration(seconds: 1), () {
          scrollController.animateTo(
            0.0,
            duration: const Duration(seconds: 1),
            curve: Curves.ease,
          );
        });
      });
    }
  }

Each Text() widget has its own scroll controller like this:

SingleChildScrollView(
    controller: widget.scrollControllerSummary,
    scrollDirection: Axis.horizontal,
    child: Text(
        softWrap: false,
        'Text here!',
    ),
)
0

There are 0 answers