Reputation: 4933
I want the listview to start with an offset. Which I am trying to achieve by using below code in the ListView.
controller: ScrollController(initialScrollOffset: 30 * ITEM_HEIGHT),
Initially on the first load the list is loaded with the correct offset.
When the list is built again by calling set state from the parent widget, the list gets updated but the scroll offset behaves weird.
There are two scenarios:
Is it because when I scroll it keeps the last scroll position and that offsets my calculation? Which I think should not happen as it is a state less widget.
class DaysManager extends StatelessWidget {
final int daysBeforeFocusDate = 30;
final int totalDaysToInit = 61;
static final double ITEM_HEIGHT = 108.00;
ScrollController scrollController;
List<Day> days;
DaysManager({DateTime focusDate}) {
final DateTime startDate =
focusDate.subtract(Duration(days: daysBeforeFocusDate));
days = List.generate(totalDaysToInit, (int index) {
return Day(
date: startDate.add(
Duration(days: index),
),
);
});
scrollController = ScrollController(initialScrollOffset: 30 *ITEM_HEIGHT);
}
@override
Widget build(BuildContext context) {
return _buildScrollView();
}
ListView _buildScrollView() {
ListView listView = ListView.builder(
cacheExtent: 0,
controller: scrollController,
itemCount: days.length,
itemBuilder: (BuildContext context, int index) {
return days[index];
});
return listView;
}
}
Upvotes: 1
Views: 3858
Reputation: 1841
I reached out the the Flutter Slack community and got an answer that works. All credit to Loushou over there. Here's a copy of that conversation.
ScrollController
saves it’s scroll position inside the PageStorage
record of the list it is attached to… not of it’s own PageStorage. because of this, when the widget is recreated, since you do not specify a new key
for the listview widget, it reuses the same key (one of the many optimizations internal to flutter for performance). you can solve this by adding two lines:
import 'dart:math';
...
ListView listView = ListView.builder(
key: ValueKey<int>(Random(DateTime.now().millisecondsSinceEpoch).nextInt(4294967296)),
...
You need to give the listview a new, random key
every time you recreate it, so that it does not load up it’s PageStorage
values.
here is the full, updated code for DaysManager
from your example code:
class DaysManager extends StatelessWidget {
final int daysBeforeFocusDate = 30;
final int totalDaysToInit = 61;
static final double ITEM_HEIGHT = 108.00;
ScrollController scrollController;
List<Day> days;
DaysManager({
DateTime focusDate,
}) {
final DateTime startDate = focusDate.subtract(Duration(days: daysBeforeFocusDate));
days = List.generate(totalDaysToInit, (int index) {
return Day(
date: startDate.add(
Duration(days: index),
),
);
});
scrollController = ScrollController(
initialScrollOffset: 30 *ITEM_HEIGHT,
);
}
@override
Widget build(BuildContext context) {
return _buildScrollView();
}
ListView _buildScrollView() {
ListView listView = ListView.builder(
key: ValueKey<int>(Random(DateTime.now().millisecondsSinceEpoch).nextInt(4294967296)),
cacheExtent: 0,
controller: scrollController,
itemCount: days.length,
itemBuilder: (BuildContext context, int index) {
return days[index];
});
return listView;
}
}
Upvotes: 8