I'm currently building a calendar view in Flutter using a SliverList and a SliverChildBuilderDelegate such that I don't have to render every single item in the calendar at once.
The first date is epoch time, Jan 1, 1970, and the last date is some odd amount of time computed after today's date.
My issue is is that when I first render the view, I want it to render the view starting today, not on Jan 1, 1970. However, if I have today as the 0 indexes, negative indices are not allowed (or supplied) to the builder delegate so you can't scroll up from that date. You also can't supply an initial index, as far as I can tell, to the builder or the list, so I can't make epoch time as the 0 indexes either since the list will just start there, making for quite the terrible experience! I'm not entirely sure how to proceed.
Does anyone have any suggestions?
In Flutter, with slivers, we can create different scrolling effects. Slivers give an amazing view of the lists when they scroll up or down. The slivers allow us to impact the Lists, Grids scrolling experience. In this article, we will be looking at Slivers features offered by the sliver_tools package.
SliverChildListDelegate: Supplies children for slivers using a widget list. SliverChildBuilderDelegate: Build the list lazily, suitable for a list with a tremendous number of items You can also check the official docs for more information.
Using sliver stuff helps us create many fancy scrolling effects and can make the scrolling process through a large number of children more efficient due to the ability to lazily build each item when it scrolls into view. SliverList needs to be implemented inside a silver group and a CustomScrollView, like this:
Many slivers lazily construct their box children to avoid creating more children than are visible through the Viewport. This delegate provides children using a NullableIndexedWidgetBuilder callback, so that the children do not even have to be built until they are displayed.
SliverList takes a delegate parameter which provides the items in the list as they scroll into view.
You can specify the actual list of children with a SliverChildListDelegate Or build them lazily with a SliverChildBuilderDelegate.
SliverList(
delegate: SliverChildListDelegate(
[
Container(color: Colors.red, height: 150.0),
Container(color: Colors.purple, height: 150.0),
Container(color: Colors.green, height: 150.0),
],
),
);
// This builds an infinite scrollable list of differently colored
// Containers.
SliverList(
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
// To convert this infinite list to a list with three items,
// uncomment the following line:
// if (index > 3) return null;
return Container(color: getRandomColor(), height: 150.0);
},
// Or, uncomment the following line:
// childCount: 3,
),
);
References: http://flutterexamples.com/#textfield
I'm not aware of an easy way to do this, there's no initialPositition
parameter in ListView
nor in SliverList
. The reason I can think of is that lists are a series of widgets embedded on a ScrollView
, such that in order for you to set an initial item, you would need to know the exact scroll offset of that item.
By default the two list widgets make no assumption about the height of its items, so in general finding that offset would require you to compute the heights of all widgets before it one by one, which is inefficient.
However, you can make things easier if you know beforehand the height of all your list items, or if you can force them a fixed height through either the ListView.itemExtent
field or the SliverFixedExtentList
.
In case you do know (or forced) the height of your list items beforehand, you can set an initial item through an initialScrollOffset
in your ScrollController
. Here's an example with a ListView
.
@override
Widget build(BuildContext context) {
final _itemExtent = 56.0; // I know item heights beforehand
final generatedList = List.generate(500, (index) => 'Item $index');
return ListView(
controller: ScrollController(initialScrollOffset: _itemExtent * 401),
children: generatedList
.map((index) =>
ListTile(title: Text(index, style: TextStyle(fontSize: 20.0))))
.toList(),
);
}
Or in a SliverList
.
@override
Widget build(BuildContext context) {
final _itemExtent = 56.0;
final generatedList = List.generate(500, (index) => 'Item $index');
return CustomScrollView(
controller: ScrollController(initialScrollOffset: _itemExtent * 401),
slivers: [
SliverFixedExtentList(
itemExtent: _itemExtent, // I'm forcing item heights
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(
title: Text(
generatedList[index],
style: TextStyle(fontSize: 20.0),
),
),
childCount: generatedList.length,
),
),
],
);
}
In both cases this is the result when you first open the app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With