Vertical and Horizontal Coordinated Scrolling of Independent Lists

Viewed 14

enter image description here

I have joined tables of data that I need to scroll together on both horizontal and vertical axis, with heading First Row that should not scroll with vertical data, but should scroll with horizontal.

You can see from my video that my simplified example below will scroll as desired vertically, but the rows, being independent do not scroll horizontally together as needed. The question is how to scroll each independent list horizontally together without losing the vertical functionality. The number of rows and columns is variable and can be quite large. My example code below is simplified to illustrate the behavior.

The below is a complete project example that can be cut and pasted into a dartpad flutter project or just click here: https://dartpad.dev/?id=6c4ea40ceee87ce9de4bcfe38ba0b750

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.light(),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: MyWidget(),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    List listDates = ['Jan', 'Feb', 'Mar', 'Apr'];
    Map<String, List> all = {
      'Todd': [1,2,3,4],
      'Mary': [5,6,7,8],
      'Henry': [9,10,11,12],
    };

    List<String> names = [];

    all.forEach((key,value) {
      names.add(key);
    });


    return Column(
      children: [
        SizedBox(
          height: 200,
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              const SizedBox(
                height: 200,
                width: 200,
              ),
              Expanded(
                child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: listDates.length,
                  itemBuilder: (context, index) {
                    return Column(
                      mainAxisSize: MainAxisSize.min,
                      mainAxisAlignment: MainAxisAlignment.end,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        SizedBox(
                          width: 200,
                          child: Center(
                            child: Text(
                              listDates[index],
                              style: const TextStyle(
                                fontWeight: FontWeight.w600,
                              ),
                              maxLines: 1,
                              textAlign: TextAlign.center,
                            ),
                          ),
                        ),
                      ],
                    );
                  },),
              ),
            ],
          ),
        ),
        Expanded(
          child: ListView.builder(
            itemCount: 3,
            itemBuilder: (context, index) {
              return Container(
                decoration: BoxDecoration(
                  color: index.isOdd ? Colors.blue.withOpacity(.2) : Colors.grey.withOpacity(.2),
                ),
                child: SizedBox(
                  height: 200,
                  width: double.infinity,
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisAlignment: MainAxisAlignment.start,
                    mainAxisSize: MainAxisSize.max,
                    children: [
                      SizedBox(
                        width: 200,
                        height: 200,
                        child: Padding(
                          padding: const EdgeInsets.all(4.0),
                          child: Text(
                            names[index],
                            style: const TextStyle(
                              fontWeight: FontWeight.w500,
                            ),
                          ),
                        ),
                      ),
                      Expanded(
                        child: ListView.builder(
                          scrollDirection: Axis.horizontal,
                          itemCount: listDates.length,
                          itemBuilder: (context, index2) {
                            List ints = all[names[index]]!;
                            return SizedBox(
                              width: 200,
                              child: Center(
                                child: Text(
                                  ints[index2].toString(),
                                  style: const TextStyle(
                                    fontWeight: FontWeight.w600,
                                  ),
                                  maxLines: 1,
                                  textAlign: TextAlign.center,
                                ),
                              ),
                            );
                          },
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),),
      ],
    );
  }
}
0 Answers
Related