Unverified Commit e8cb0295 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Fix SliverMainAxisGroup geometry cacheExtent (#142482)

Fixes https://github.com/flutter/flutter/issues/142183

This fixes a bug in the SliverGeometry of SliverMainAxisGroup. The cacheExtent represents how many pixels the sliver has consumed in the SliverConstraints.remainingCacheExtent. Since it was not set, slivers that came after a SliverMainAxisGroup that filled the whole screen did not properly lay out their own children, in some cases making lazy sliver more eager than they should be.
parent 5bb4fa35
......@@ -284,9 +284,21 @@ class RenderSliverMainAxisGroup extends RenderSliver with ContainerRenderObjectM
offset += child.geometry!.scrollExtent;
child = childAfter(child);
}
final double paintExtent = calculatePaintOffset(
constraints,
from: math.min(constraints.scrollOffset, 0),
to: totalScrollExtent,
);
final double cacheExtent = calculateCacheOffset(
constraints,
from: math.min(constraints.scrollOffset, 0),
to: totalScrollExtent,
);
geometry = SliverGeometry(
scrollExtent: totalScrollExtent,
paintExtent: calculatePaintOffset(constraints, from: 0, to: totalScrollExtent),
paintExtent: paintExtent,
cacheExtent: cacheExtent,
maxPaintExtent: maxPaintExtent,
hasVisualOverflow: totalScrollExtent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
);
......
......@@ -692,6 +692,42 @@ void main() {
expect(controller.offset, 1000);
expect(counter, equals(2));
});
testWidgets('SliverMainAxisGroup does not cause extra builds for lazy sliver children', (WidgetTester tester) async {
// By setting the correct SliverGeometry in the first SliverMainAxisGroup,
// the following SliverMainAxisGroups will not perform extra work.
final Map<int, int> buildsPerGroup = <int, int>{
0 : 0,
1 : 0,
2 : 0,
};
await tester.pumpWidget(MaterialApp(
home: CustomScrollView(
slivers: <Widget>[
for (int groupIndex = 0; groupIndex < 3; groupIndex++)
SliverMainAxisGroup(
slivers: <Widget>[
SliverList.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
buildsPerGroup[groupIndex] = buildsPerGroup[groupIndex]! + 1;
return const SizedBox.square(dimension: 50);
},
),
],
),
]
),
));
await tester.pumpAndSettle();
expect(buildsPerGroup[0], 17); // First sliver filled the screen and cache extent
expect(buildsPerGroup[1], 1); // Second only lays out one child
expect(buildsPerGroup[2], 1); // Third only lays out one child
final RenderSliverMainAxisGroup renderGroup = tester.renderObject(
find.byType(SliverMainAxisGroup).first,
) as RenderSliverMainAxisGroup;
expect(renderGroup.geometry!.cacheExtent, 850.0);
});
}
Widget _buildSliverList({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment