I am creating a flutter Web application, but have issues when resizing the window with a SingleChildScrollView + ScrollController.
When I resize the browser window, the page "snaps" back up to the very top. Being a web app, most of the page "sections" are made from Columns with responsively coded widgets as children, with such widgets as Flexible or Expanded. From what I have read, the SingleChildScrollView widget doesn't work well with Flexible or Expanded widgets, so I thought that may be my issue.
For testing purposes, I created a new page with a single SizedBox that had a height of 3000, which would allow me to scroll. After scrolling to the bottom and resizing the window, I was still snapped up to the top of the page. Thus, with or without using Expanded or Flexible widgets, I have the same result.
Test with a SizedBox only
@override
Widget build(BuildContext context) {
return Scaffold(
color: Colors.white,
body: SingleChildScrollView(
controller: controller.scrollController,
primary: false,
child: Column(
children: [
SizedBox(
width: 150,
height: 3000,
),
],
),
),
);
}
I am using Getx with this project to try getting a demo app up and running a bit quicker while I am still learning the core concepts. Below is my controller.
Controller
class HomePageScrollControllerX extends GetxController {
late ScrollController scrollController;
@override
void onInit() {
super.onInit();
scrollController = ScrollController(
initialScrollOffset: 0.0,
keepScrollOffset: true,
);
}
}
Thank you in advance for any insight on this subject!
EDIT
I have added a listener on my ScrollController, which is able to print to the console that I am scrolling. However, the listener does not get called when I resize the window (tested in both Chrome and Edge).
Currently, I believe my only option is to use the listener to update an "offset" variable in the controller, and pass the window's width over to the controller when the widget rebuilds. If done properly, I should be able to use the controller to scroll to the saved offset. Something like this:
if (scrollController.hasClients) {
if (offset > scrollController.position.maxScrollExtent) {
scrollController.jumpTo(scrollController.position.maxScrollExtent);
} else if (offset < scrollController.position.minScrollExtent) {
scrollController.jumpTo(scrollController.position.minScrollExtent);
} else {
scrollController.jumpTo(offset);
}
}
However, I feel like this shouldn't be necessary - and I bet this solution would be visually evident to the user.
Edit 2
While I did get this to work with adding the below code just before the return statement, it appears that my initial thoughts were correct. When I grab the edge of the window and move it, it pops up to the top of the window, then will jump to the correct scroll position. It looks absolutely terrible!
@override
Widget build(BuildContext context) {
Future.delayed(Duration.zero, () {
controller.setWindowWithAndScroll(MediaQuery.of(context).size.width);
});
return PreferredScaffold(
color: Colors.white,
body: SingleChildScrollView(
controller: controller.scrollController,
......