Michał Sułek
Michał Sułek

Reputation: 287

How to sync scroll two SingleChildScrollView widgets

How to sync scroll two SingleChildScrollView widgets ?

    new Positioned(
        child: new SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: new Scale() 
            ), 
        ),
    new Positioned(
        child: new SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: new chart()
        )
    )

I need those two widgets to have exactly same scroll position ( both have same width and can be scrolled only horizontally ). It must sync after user action and when changed in code.

Upvotes: 4

Views: 4142

Answers (3)

Priyank Patel
Priyank Patel

Reputation: 51

I was just facing the same problem, and there's now an official package for that: linked_scroll_controller (https://pub.dev/packages/linked_scroll_controller).

Using that package, you just have to create a master LinkedScrollControllerGroup(https://pub.dev/documentation/linked_scroll_controller/latest/linked_scroll_controller/LinkedScrollControllerGroup-class.html) to keep track of the scroll offset and it'll then provide you separate ScrollControllers (kept in sync) via LinkedScrollControllerGroup.addAndGet()(https://pub.dev/documentation/linked_scroll_controller/latest/linked_scroll_controller/LinkedScrollControllerGroup/addAndGet.html).

Upvotes: 0

Sreevardhan Reddy
Sreevardhan Reddy

Reputation: 731

like xster said, you have to use scrollcontroller on one scrollview and notification Listener on another scrollview, here is the code.

class StackO extends StatefulWidget {
  // const stack({Key key}) : super(key: key);

  @override
  _StackOState createState() => _StackOState();
}

class _StackOState extends State<StackO> {
  ScrollController _scrollController = new ScrollController();

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: <Widget>[
          new Positioned(
            child: new SingleChildScrollView(
              controller: _scrollController,
              scrollDirection: Axis.horizontal,
              child: new Scale() // your widgets,
            ),
          ),
          new Positioned(
            child: new NotificationListener<ScrollNotification>(
              onNotification: (ScrollNotification scrollInfo) {
                print('scrolling.... ${scrollInfo.metrics.pixels}');
                _scrollController.jumpTo(scrollInfo.metrics.pixels);
                return false;
              },
              child: SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: new chart() // your widgets,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Upvotes: 6

xster
xster

Reputation: 6667

For input, you control them via a ScrollController passed in as a constructor parameter.

For output, you can use a NotificationListener to listen to movements on one and then use the ScrollController to sync them together.

You can either listen to something like https://docs.flutter.io/flutter/widgets/UserScrollNotification-class.html to keep them tightly bound or wait for https://docs.flutter.io/flutter/widgets/ScrollEndNotification-class.html and then call https://docs.flutter.io/flutter/widgets/ScrollController/animateTo.html on the ScrollController.

Upvotes: 2

Related Questions