# Synchronize the scrolling of your ListViews in Flutter

In my current project, I have a requirement where I display multiple `ListView`s below each other and these lists must scroll together. It does not matter which list is scrolled by the user, the other one should follow it. 

You can use `ScrollController` when you want to manage the scrolling of a `ListView`. 
My first idea was to use the same controller for each list, but that won't work, it will not update the list that is not scrolled.

Another option would be to implement the synchronization by listening to changes on the controllers. But there is a great package that could help us and it is made by Google developers, the [linked_scroll_controller](https://pub.dev/packages/linked_scroll_controller).

Let's see how we can use it.

Let's say we have 2 horizontal list views below each other.
```dart
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Awesome list 1'),
            SizedBox(
              height: 150,
              // First list
              child: ListView.builder(
                scrollDirection: Axis.horizontal,
                itemBuilder: (context, index) => _ListItem(
                  index: index,
                ),
              ),
            ),
            const Divider(),
            const Text('Awesome list 2'),
            SizedBox(
              height: 150,
              // Second list
              child: ListView.builder(
                scrollDirection: Axis.horizontal,
                itemBuilder: (context, index) => _ListItem(
                  index: index,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _ListItem extends StatelessWidget {
  const _ListItem({
    Key? key,
    required this.index,
  }) : super(key: key);
  final int index;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text('List item $index'),
        ),
      ),
    );
  }
}
```
This is how it looks like

![scroll.gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1643998252814/dPj_02REs.gif?height=500)

Let's synchronize our lists.

First we need to add [linked_scroll_controller](https://pub.dev/packages/linked_scroll_controller) to our dependencies in `pubspec.yaml`:
```yml
dependencies:
  linked_scroll_controller: ^0.2.0
```

Then we need to create the scroll controller group, which will manage the synchronization for us.


```dart
class _MyHomePageState extends State<MyHomePage> {
  // Create a new scoll controller group
  late final LinkedScrollControllerGroup _controllerGroup =
      LinkedScrollControllerGroup();
  // Create 2 new scroll controllers in the group, so they are connected.
  late final ScrollController _controller1 = _controllerGroup.addAndGet();
  late final ScrollController _controller2 = _controllerGroup.addAndGet();

  // ...
}
```

Then we just need to add the 2 controllers to our `ListView`s.

```dart
// ...
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    const Text('Awesome list 1'),
    SizedBox(
      height: 150,
      child: ListView.builder(
        // Use the controller
        controller: _controller1,
        scrollDirection: Axis.horizontal,
        itemBuilder: (context, index) => _ListItem(
          index: index,
        ),
      ),
    ),
    const Divider(),
    const Text('Awesome list 2'),
    SizedBox(
      height: 150,
      child: ListView.builder(
        // Use the controller
        controller: _controller2,
        scrollDirection: Axis.horizontal,
        itemBuilder: (context, index) => _ListItem(
          index: index,
        ),
      ),
    ),
  ],
),
// ...
```

This is how it works:

![scroll_sync.gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1643999082533/wFQ142HQE.gif?height=500)

That's it!

You can find the source code at https://github.com/dtengeri/linked_list_views_example

