I have a PageView and I want to use it to show an indefinite amount of widgets in columns. I'm trying to add widgets to a column until it would overflow, and then build the next page beginning with the widget that would have overflowed.
So far, this is what I've hacked together in an effort to get something working:
class OverflowSliverChildDelegate extends SliverChildDelegate {
OverflowSliverChildDelegate({
@required this.itemBuilder,
}) : assert(itemBuilder != null),
super();
/// Used to build individual items to slot into pages.
final IndexedWidgetBuilder itemBuilder;
@override
Widget build(BuildContext context, int index) {
return LayoutBuilder(
builder: (context, constraints) {
// todo: handle this better
if (remainingHeight <= 0) throw Error();
var itemIndex = 0;
return PageView.builder(
itemBuilder: (context, pageIndex) {
final remainingHeight = constraints.maxHeight;
return Column(
// todo: move this generator to a separate method
children: () sync* {
// Build widgets until we run out of vertical space.
while (remainingHeight > 0) {
// todo: layout widget and get its height
final widget = itemBuilder(context, itemIndex++);
// remainingHeight -= widget.height
yield widget;
}
}(),
);
},
);
},
);
}
}
If I was only concerned with text, I could use a TextPainter to layout the text and get the height. Is there a way to do this for arbitrary widgets (which may or may not have children of their own)?
Update
After looking into the Offstage widget, I tried this but Flutter is asserting that I don't call the size getter from outside the object. I felt so close to a solution too.
while (remainingHeight > 0) {
final widget = itemBuilder(context, itemIndex++);
final renderObj = ConstrainedBox(
child: widget,
constraints: constraints.copyWith(
maxHeight: remainingHeight,
),
).createRenderObject(context);
renderObj.layout(constraints);
remainingHeight -= renderObj.size.height;
if (remainingHeight > 0) {
yield widget;
}
}
