Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ScrollController attached to multiple scroll views

Tags:

flutter

I have a stateful widget with children as such

final _scrollController = TrackingScrollController();

PageView(
  controller: _pageController,
  children: <Widget>[
    _ListView(controller: _scrollController),
    _ListView(controller: _scrollController),
    _ListView(controller: _scrollController),
  ],
)

This seems to match the pattern shown here https://docs.flutter.io/flutter/widgets/TrackingScrollController-class.html

However, when I scroll one list, the others are not synced, and I get this error for every frame

flutter: Another exception was thrown: ScrollController attached to multiple scroll views.

Any ideas as to what I'm doing wrong? Do I have unreasonable expectations of TrackingScrollController?

like image 337
Luke Pighetti Avatar asked Sep 04 '18 16:09

Luke Pighetti


1 Answers

Please see Ashton Thomas' explanation for why TrackingScrollController doesn't work for this use case. To achieve the behavior you described, you can use a new package released by Google: linked_scroll_controller.

First, add this package to your pubspec.yaml:

dependencies:
  linked_scroll_controller: ^0.1.2
  // ...

And then integrate it into your code like this:

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  final _pageController = PageController();

  // This group keeps track of the synchronized scroll offset.
  final _scrollControllerGroup = LinkedScrollControllerGroup();
  ScrollController _scrollController1;
  ScrollController _scrollController2;
  ScrollController _scrollController3;

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

    // Create separate ScrollControllers as you need them:
    _scrollController1 = _scrollControllerGroup.addAndGet();
    _scrollController2 = _scrollControllerGroup.addAndGet();
    _scrollController3 = _scrollControllerGroup.addAndGet();
  }

  @override
  void dispose() {
    // Don't forget to dispose all of your controllers!
    _pageController.dispose();
    _scrollController1.dispose();
    _scrollController2.dispose();
    _scrollController3.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return PageView(
      controller: _pageController,
      children: <Widget>[
        // Use controllers only once:
        ListView(controller: _scrollController1),
        ListView(controller: _scrollController2),
        ListView(controller: _scrollController3),
      ],
    );
  }
}
like image 132
Jonas Wanke Avatar answered Oct 21 '22 00:10

Jonas Wanke