I want all the rows should get scrolled together with multiple controller and without use of linked_scroll_controller.
This code snippet serves as an example. I acknowledge that the issue could be resolved by enveloping the column with a single-child scroll view instead of rows. However, the stipulation is to address this problem without utilizing that approach and linked_scroll_controller.
import 'package:flutter/material.dart';
class SynchroniseScroll extends StatelessWidget {
SynchroniseScroll({super.key});
final ScrollController header = ScrollController();
final ScrollController body = ScrollController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('DropdownFormField Example'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...List.generate(
4,
(index) => Padding(
padding: const EdgeInsets.only(top: 18.0),
child: SingleChildScrollView(
controller: index == 0 ? header : body,
scrollDirection: Axis.horizontal,
child: Row(
children: [
...List.generate(
25,
(index) => Container(
height: 100,
width: 100,
color: index.isEven
? Colors.yellowAccent
: Colors.purpleAccent,
),
)
],
),
),
),
),
],
),
);
}
}
Inspect the output provided below; when I scroll the row at the 2nd index, the remaining rows do not scroll in tandem.
You need to add listeners to your ScrollControllers
and then act upon the changes reported through those listeners.
In the code below, there are listeners added to the controllers (one for each row) and in the _handleScrollNotification
method you can see how all 3 other ScrollControllers
are told to jumpTo
the same location as the one that was reported by the one ScrollController
that recorded a change:
class SynchroniseScroll extends StatefulWidget {
const SynchroniseScroll({super.key});
@override
State<SynchroniseScroll> createState() => _SynchroniseScrollState();
}
class _SynchroniseScrollState extends State<SynchroniseScroll> {
List<ScrollController> controllers = [];
@override
void initState() {
controllers = List.generate(4, (index) => ScrollController());
controllers.forEach((controller) =>
controller.addListener((() => _handleScrollNotification(controller))));
super.initState();
}
void _handleScrollNotification(ScrollController controller) {
print(controller.position.pixels);
controllers
.where((element) => element != controller)
.forEach((contr) => contr.jumpTo(controller.position.pixels));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DropdownFormField Example'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: controllers
.map((controller) => Padding(
padding: const EdgeInsets.only(top: 18.0),
child: SingleChildScrollView(
controller: controller,
scrollDirection: Axis.horizontal,
child: Row(
children: [
...List.generate(
25,
(index) => Container(
height: 100,
width: 100,
color: index.isEven
? Colors.yellowAccent
: Colors.purpleAccent,
),
)
],
),
),
))
.toList(),
),
);
}
@override
void dispose() {
controllers.forEach((e) => e.dispose());
super.dispose();
}
}