how to scroll two listview builder simultaneously inside the pageview builder

Viewed 49

I add the two listviews builder in pageViewbuilder, the two listviews are separetly scrollable,but I want that the both listviews are scrollable in simultaneously in flutter

1 Answers

The solution is to synchronize the scroll between two ListViews by listening to scroll events with NotificationListener<ScrollNotification>. Whenever a scroll event is emitted from one ListView set the other ListView controller to jump to the same position.

One optimization is to ignore notifications on the other ListView if the first or second one is already scrolling. But it also works without this optimization.

This is the result (Check also out the live demo on DartPad).

Screenshot

Sources:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

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

enum ScrollingList {
  none,
  left,
  right,
}

class _MyHomePageState extends State {
  late final ScrollController _controllerLeft;
  late final ScrollController _controllerRight;
  var scrollingList = ScrollingList.none;

  @override
  void initState() {
    super.initState();
    _controllerLeft = ScrollController();
    _controllerRight = ScrollController();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          Expanded(
            child: NotificationListener<ScrollNotification>(
              onNotification: (notification) {
                if (notification is ScrollStartNotification) {
                  if (scrollingList == ScrollingList.none) {
                    scrollingList = ScrollingList.left;
                  }
                } else if (notification is ScrollEndNotification) {
                  if (scrollingList == ScrollingList.left) {
                    scrollingList = ScrollingList.none;
                  }
                }
                if (scrollingList == ScrollingList.left) {
                  _controllerRight.jumpTo(_controllerLeft.offset);
                }
                return true;
              },
              child: ListView.separated(
                controller: _controllerLeft,
                itemBuilder: (context, index) {
                  return Text('Item a$index');
                },
                separatorBuilder: (context, index) {
                  return const Divider();
                },
                itemCount: 100,
              ),
            ),
          ),
          const VerticalDivider(),
          Expanded(
            child: NotificationListener<ScrollNotification>(
              onNotification: (notification) {
                if (notification is ScrollStartNotification) {
                  if (scrollingList == ScrollingList.none) {
                    scrollingList = ScrollingList.right;
                  }
                } else if (notification is ScrollEndNotification) {
                  if (scrollingList == ScrollingList.right) {
                    scrollingList = ScrollingList.none;
                  }
                }
                if (scrollingList == ScrollingList.right) {
                  _controllerLeft.jumpTo(_controllerRight.offset);
                }
                return true;
              },
              child: ListView.separated(
                controller: _controllerRight,
                itemBuilder: (context, index) {
                  return Text('Item b$index');
                },
                separatorBuilder: (context, index) {
                  return const Divider();
                },
                itemCount: 100,
              ),
            ),
          ),
        ],
      ),
    );
  }
}
Related