Which class to extend when creating slivers?
Say, I have a class FooSliver
which returns a widget.
class FooSliver extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaybeSliverWidget(...);
}
}
But I can't use this class directly in my slivers if the above class returns a non-sliver widget i.e. a RenderObject
.
CustomScrollView(
slivers: [
FooSliver(),
],
)
So, which sliver class should I extend instead of StatelessWidget
to make sure I always return a sliver widget from it?
CodePudding user response:
You can create your custom sliver. You need to create a custom RenderSliverSingleBoxAdapter
and SingleChildRenderObjectWidget
class FooSliver extends SingleChildRenderObjectWidget {
const FooSliver({super.key, super.child});
@override
RenderObject createRenderObject(BuildContext context) => FooRenderSliver();
}
class BarSliver extends SingleChildRenderObjectWidget {
const BarSliver({super.key, super.child = const Text("Hello from Bar")});
@override
RenderObject createRenderObject(BuildContext context) => FooRenderSliver();
}
class FooRenderSliver extends RenderSliverSingleBoxAdapter {
FooRenderSliver({super.child});
@override
void performLayout() {
/// from [RenderSliverToBoxAdapter]
if (child == null) {
geometry = SliverGeometry.zero;
return;
}
final SliverConstraints constraints = this.constraints;
child!.layout(constraints.asBoxConstraints(), parentUsesSize: true);
final double childExtent;
switch (constraints.axis) {
case Axis.horizontal:
childExtent = child!.size.width;
break;
case Axis.vertical:
childExtent = child!.size.height;
break;
}
assert(childExtent != null);
final double paintedChildSize =
calculatePaintOffset(constraints, from: 0.0, to: childExtent);
final double cacheExtent =
calculateCacheOffset(constraints, from: 0.0, to: childExtent);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = SliverGeometry(
scrollExtent: childExtent,
paintExtent: paintedChildSize,
cacheExtent: cacheExtent,
maxPaintExtent: childExtent,
hitTestExtent: paintedChildSize,
hasVisualOverflow: childExtent > constraints.remainingPaintExtent ||
constraints.scrollOffset > 0.0,
);
setChildParentData(child!, constraints, geometry!);
}
}
And use like
home: Scaffold(
body: CustomScrollView(
slivers: [
FooSliver(
child: Text("Hi From Foo sliver"),
),
BarSliver()
],
),
),
More about RenderSliver