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.