Synchronising ListView Scroll Positions

Viewed 1084

I'm trying to give this screen a specific scroll behaviour. Each row has the data provided to it using the BLoC pattern.
The left side of the screen needs to only be scrolled vertically, whilst the right side needs to be scrolled both horizontally and vertically.
I'm currently doing this by having two separate list views for vertical scroll and sharing the BLoC. The right side widgets are then wrapped in a list view moving in the opposite direction.

enter image description here

I need to synchronise the vertical and horizontal list views (and potentially scroll views in the future) and haven't been able to successfully ensure the scroll positions are kept in sync. How can I sync multiple list view positions? Here is the code snippet for what I'm trying to do:

class ComposePage extends StatefulWidget {
  @override
  _ComposePageState createState() => _ComposePageState();
}

class _ComposePageState extends State<ComposePage> {
  final TrackingScrollController _scrollController = TrackingScrollController();

  @override
  Widget build(BuildContext context) {
    return Container(
      child: NotificationListener<ScrollNotification>(
        onNotification: (notification) {
          print("SCROLL");
      
_scrollController.position.setPixels(notification.metrics.pixels);
          for (ScrollPosition position in _scrollController.position)
            position.setPixels(notification.metrics.pixels);
        },
        child: Column(
          verticalDirection: VerticalDirection.up,
          children: <Widget>[
            Expanded(
              flex: 8,
              child: Material(
                type: MaterialType.canvas,
                elevation: 1.0,
                child: _buildBuildComposeContent(_scrollController),
              ),
            ),
            Expanded(
              flex: 1,
              child: Material(
                type: MaterialType.canvas,
                elevation: 20.0,
                child: ControlsHeader(),
              ),
            )
          ],
        ),
      ),
      color: Colors.green,
    );
  }

  _buildBuildComposeContent(TrackingScrollController scrollController) {
    return Container(
      child: Row(
        children: <Widget>[
          Expanded(
            flex: 1,
            child: _buildLabelArea(scrollController),
          ),
          Expanded(
            flex: 7,
            child: _buildEditArea(scrollController),
          ),
        ],
      ),
    );
  }

  Column _buildLabelArea(TrackingScrollController controller) {
    return Column(
      children: [
        Expanded(
          flex: 1,
          child: Container(
            color: Colors.pink,
          ),
        ),
        Expanded(
          flex: 8,
          child: ListView(
            scrollDirection: Axis.vertical,
            controller: controller,
            children: <Widget>[
              BlocProvider(
                bloc: TrackBloc(),
                child: TrackLabel(),
              ),
              BlocProvider(
                bloc: TrackBloc(),
                child: TrackLabel(),
              ),
              BlocProvider(
                bloc: TrackBloc(),
                child: TrackLabel(),
              ),
              BlocProvider(
                bloc: TrackBloc(),
                child: TrackLabel(),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Column _buildEditArea(TrackingScrollController controller) {
    return Column(
      children: <Widget>[
        Expanded(
          flex: 1,
          child: Playhead(),
        ),
        Expanded(
          flex: 8,
          child: Container(
            child: ListView(
              scrollDirection: Axis.vertical,
              controller: controller,
              children: <Widget>[
                BlocProvider(
                  bloc: TrackBloc(),
                  child: TrackView(isEditable: true),
                ),
                BlocProvider(
                  bloc: TrackBloc(),
                  child: TrackView(isEditable: true),
                ),
                BlocProvider(
                  bloc: TrackBloc(),
                  child: TrackView(isEditable: true),
                ),
                BlocProvider(
                  bloc: TrackBloc(),
                  child: TrackView(isEditable: true),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}
1 Answers
Related