I created a custom widget that adds a footer as last item to a received scrollable widget. Everything works fine, but I want to change the time the footer is being created.
Like ListView.builder creates items as they're scrolled onto the screen, I want that happen with the footer too. If this custom widget receives a ListView.builder or GridView.builder, their items are being created fine as they're scrolled onto the screen, but the footer is created the first time even if it's not on the screen.
Here is the custom widget, where the received widget is widget.child (ScrollView) and the footer is widget.footer (Widget).
@override
Widget build(BuildContext context) {
return Scrollable(
controller: widget.child.controller,
axisDirection: widget.child.getDirection(context),
viewportBuilder: (context, offset) {
return ShrinkWrappingViewport(
axisDirection: widget.child.getDirection(context),
offset: offset,
slivers: widget.child.buildSlivers(context)
..add(
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
print('footer');
return widget.footer;
}, childCount: 1))),
);
},
);
}
This is how I'm using it:
ScrollableWithFooter(
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
print(index);
return SizedBox(height: 400, child: Text('Item $index'));
},
),
footer: Center(child: Text('Footer')),
)
With a list of 50, I'm seeing the first items on the screen and this is the output of the prints:
I/flutter (28472): 0
I/flutter (28472): 1
I/flutter (28472): 2
I/flutter (28472): footer
And when I start scrolling, the other items start printing their indexes as they're created:
I/flutter (28472): 2
I/flutter (28472): footer
I/flutter (28472): 3
I/flutter (28472): 4
I/flutter (28472): 5
This is correct for the items but not for the footer. I want the footer to be created when I reached the end of the list, like the other items. How can achieve that?
Note that on the screen everything works fine, the footer appears at the end of the list. It's only its creation that happens before it should.
This is something I tried, but it doesn't work:
@override
Widget build(BuildContext context) {
return Scrollable(
controller: widget.child.controller,
axisDirection: widget.child.getDirection(context),
viewportBuilder: (context, offset) {
List<Widget> slivers = widget.child.buildSlivers(context);
return ShrinkWrappingViewport(
axisDirection: widget.child.getDirection(context),
offset: offset,
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
if (index < slivers.length) {
return slivers[index]; // <- Here seems to be the problem
}
print('footer');
return widget.footer;
}, childCount: slivers.length + 1))
],
);
},
);
}
I get this error:
The following assertion was thrown building NotificationListener<KeepAliveNotification>:
I/flutter (28472): A RenderRepaintBoundary expected a child of type RenderBox but received a child of type
I/flutter (28472): RenderSliverPadding.