Home > other >  Flutter Scroll multiple ListViews together without the separators between them
Flutter Scroll multiple ListViews together without the separators between them

Time:07-12

I am trying to build a vertical ListView of with horizontal ListViews. My problem is, that I want to scroll all the Rows together without scrolling the separators between the Rows. That is why I can't just use a SingleChildScrollView around all of this. I know Flutter does not allow to use one ScrollConroller for multiple Widgets. Is there a way to accomplish this?

This is a simplified code example of my problem:

class ListViewTest extends StatelessWidget{

   final ScrollController _horizontalScrollController = ScrollController(); 
  
  @override
  Widget build(BuildContext context) {
    return ListView.separated(
      itemCount: 20,
      separatorBuilder: (BuildContext context, int i) => const Divider(
        thickness: 1,
        color: Colors.black,
        height: 41,
      ),
      itemBuilder: (BuildContext context, int i) => SizedBox(
        height: 40,
        child: ListView.separated(
          //controller: _horizontalScrollController, does not work
          shrinkWrap: true,
          scrollDirection: Axis.horizontal,
          itemCount: 10,
          separatorBuilder: (context, j) => SizedBox(width: 5,),
          itemBuilder: (context, j) =>  Container(
            height: 40,
            width: 60,
            color: Colors.green,
            child: Text(
              "cell $i - $j"
            ),
          ),
        ),
      ),
    );
  }
}

Edit:


See it as a Table with a Divider for each Row. Currently I can scroll the entire table vertically. But horizontally I can only scroll one Row at once. What I want is to scroll one Row and all other Rows to follow, so that all Columns are aligned. But the Dividers should not move horizontally.

CodePudding user response:

If you're okay with adding an extra package to solve your problem, there's an excellent solution from google.dev team that does just what you need: linked_scroll_controller

An implementation based on your example would be rather trivial:

class ListViewTest extends StatelessWidget{

   final _controllerGroup = LinkedScrollControllerGroup(); 
  
  @override
  Widget build(BuildContext context) {
    return ListView.separated(
      itemCount: 20,
      separatorBuilder: (BuildContext context, int i) => const 
        Container(
        child: Text('Column-Divider'),
        height: 41,
      ),
      itemBuilder: (BuildContext context, int i) => SizedBox(
        height: 40,
        child: ListView.separated(
          key: Key('$i'),
          controller: _controllerGroup.addAndGet(), // << add here
          shrinkWrap: true,
          scrollDirection: Axis.horizontal,
          itemCount: 10,
          separatorBuilder: (context, j) => SizedBox(width: 5,),
          itemBuilder: (context, j) =>  Container(
            height: 40,
            width: 60,
            color: Colors.green,
            child: Text(
              "cell $i - $j"
            ),
          ),
        ),
      ),
    );
  }
}

Keep in mind the note from the package:

If you add controllers dynamically, the corresponding scrollables must be given unique keys to avoid the scroll offset going out of sync.

  • Related