mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Fix SliverMainAxisGroup layout in reverse (#145572)
Fixes https://github.com/flutter/flutter/issues/145068
The original tests for SliverMainAxisGroup did not actually check where the child was painted (#126596).
Followed the same pattern in RenderSliverMultiBoxAdaptor:
11c034f037/packages/flutter/lib/src/rendering/sliver_multi_box_adaptor.dart (L666)
This commit is contained in:
parent
bd909542a3
commit
6d7922f3f5
@ -274,8 +274,8 @@ class RenderSliverMainAxisGroup extends RenderSliver with ContainerRenderObjectM
|
||||
assert(() {
|
||||
if (child != null && maxPaintExtent.isInfinite) {
|
||||
throw FlutterError(
|
||||
'Unreachable sliver found, you may have a sliver behind '
|
||||
'a sliver with infinite extent. '
|
||||
'Unreachable sliver found, you may have a sliver following '
|
||||
'a sliver with an infinite extent. '
|
||||
);
|
||||
}
|
||||
return true;
|
||||
@ -327,12 +327,50 @@ class RenderSliverMainAxisGroup extends RenderSliver with ContainerRenderObjectM
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
RenderSliver? child = lastChild;
|
||||
if (firstChild == null) {
|
||||
return;
|
||||
}
|
||||
// offset is to the top-left corner, regardless of our axis direction.
|
||||
// originOffset gives us the delta from the real origin to the origin in the axis direction.
|
||||
final Offset mainAxisUnit, crossAxisUnit, originOffset;
|
||||
final bool addExtent;
|
||||
switch (applyGrowthDirectionToAxisDirection(constraints.axisDirection, constraints.growthDirection)) {
|
||||
case AxisDirection.up:
|
||||
mainAxisUnit = const Offset(0.0, -1.0);
|
||||
crossAxisUnit = const Offset(1.0, 0.0);
|
||||
originOffset = offset + Offset(0.0, geometry!.paintExtent);
|
||||
addExtent = true;
|
||||
case AxisDirection.right:
|
||||
mainAxisUnit = const Offset(1.0, 0.0);
|
||||
crossAxisUnit = const Offset(0.0, 1.0);
|
||||
originOffset = offset;
|
||||
addExtent = false;
|
||||
case AxisDirection.down:
|
||||
mainAxisUnit = const Offset(0.0, 1.0);
|
||||
crossAxisUnit = const Offset(1.0, 0.0);
|
||||
originOffset = offset;
|
||||
addExtent = false;
|
||||
case AxisDirection.left:
|
||||
mainAxisUnit = const Offset(-1.0, 0.0);
|
||||
crossAxisUnit = const Offset(0.0, 1.0);
|
||||
originOffset = offset + Offset(geometry!.paintExtent, 0.0);
|
||||
addExtent = true;
|
||||
}
|
||||
|
||||
RenderSliver? child = lastChild;
|
||||
while (child != null) {
|
||||
final double mainAxisDelta = childMainAxisPosition(child);
|
||||
final double crossAxisDelta = childCrossAxisPosition(child);
|
||||
Offset childOffset = Offset(
|
||||
originOffset.dx + mainAxisUnit.dx * mainAxisDelta + crossAxisUnit.dx * crossAxisDelta,
|
||||
originOffset.dy + mainAxisUnit.dy * mainAxisDelta + crossAxisUnit.dy * crossAxisDelta,
|
||||
);
|
||||
if (addExtent) {
|
||||
childOffset += mainAxisUnit * child.geometry!.paintExtent;
|
||||
}
|
||||
|
||||
if (child.geometry!.visible) {
|
||||
final SliverPhysicalParentData childParentData = child.parentData! as SliverPhysicalParentData;
|
||||
context.paintChild(child, offset + childParentData.paintOffset);
|
||||
context.paintChild(child, childOffset);
|
||||
}
|
||||
child = childBefore(child);
|
||||
}
|
||||
|
@ -32,9 +32,16 @@ void main() {
|
||||
expect(controller.offset, 0);
|
||||
|
||||
expect(find.text('Group 0 Tile 0'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 0')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 300.0, 300.0),
|
||||
);
|
||||
expect(find.text('Group 0 Tile 1'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 1')),
|
||||
const Rect.fromLTRB(0.0, 300.0, 300.0, 600.0),
|
||||
);
|
||||
expect(find.text('Group 0 Tile 2'), findsNothing);
|
||||
|
||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||
|
||||
const double scrollOffset = 19 * 300.0;
|
||||
@ -44,7 +51,15 @@ void main() {
|
||||
expect(controller.offset, scrollOffset);
|
||||
expect(find.text('Group 0 Tile 18'), findsNothing);
|
||||
expect(find.text('Group 0 Tile 19'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 19')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 300.0, 300.0),
|
||||
);
|
||||
expect(find.text('Group 1 Tile 0'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 1 Tile 0')),
|
||||
const Rect.fromLTRB(0.0, 300.0, 300.0, 500.0),
|
||||
);
|
||||
|
||||
final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
|
||||
final RenderSliverList first = renderSlivers[0];
|
||||
@ -85,9 +100,16 @@ void main() {
|
||||
expect(controller.offset, 0);
|
||||
|
||||
expect(find.text('Group 0 Tile 0'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 0')),
|
||||
const Rect.fromLTRB(0.0, 300.0, 300.0, 600.0),
|
||||
);
|
||||
expect(find.text('Group 0 Tile 1'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 1')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 300.0, 300.0),
|
||||
);
|
||||
expect(find.text('Group 0 Tile 2'), findsNothing);
|
||||
|
||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||
|
||||
const double scrollOffset = 19 * 300.0;
|
||||
@ -97,7 +119,15 @@ void main() {
|
||||
expect(controller.offset, scrollOffset);
|
||||
expect(find.text('Group 0 Tile 18'), findsNothing);
|
||||
expect(find.text('Group 0 Tile 19'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 19')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 300.0, 300.0),
|
||||
);
|
||||
expect(find.text('Group 1 Tile 0'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 1 Tile 0')),
|
||||
const Rect.fromLTRB(0.0, 400.0, 300.0, 600.0),
|
||||
);
|
||||
|
||||
final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
|
||||
final RenderSliverList first = renderSlivers[0];
|
||||
@ -138,8 +168,11 @@ void main() {
|
||||
expect(controller.offset, 0);
|
||||
|
||||
expect(find.text('Group 0 Tile 0'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 0')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 300.0, 600.0),
|
||||
);
|
||||
expect(find.text('Group 0 Tile 1'), findsNothing);
|
||||
|
||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||
|
||||
const double scrollOffset = 19 * 300.0;
|
||||
@ -149,6 +182,10 @@ void main() {
|
||||
expect(controller.offset, scrollOffset);
|
||||
expect(find.text('Group 0 Tile 18'), findsNothing);
|
||||
expect(find.text('Group 0 Tile 19'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 19')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 300.0, 600.0),
|
||||
);
|
||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||
|
||||
const double scrollOffset2 = 20 * 300.0;
|
||||
@ -156,6 +193,10 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Group 0 Tile 19'), findsNothing);
|
||||
expect(find.text('Group 1 Tile 0'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 1 Tile 0')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 200.0, 600.0),
|
||||
);
|
||||
|
||||
final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
|
||||
final RenderSliverList first = renderSlivers[0];
|
||||
@ -197,8 +238,11 @@ void main() {
|
||||
expect(controller.offset, 0);
|
||||
|
||||
expect(find.text('Group 0 Tile 0'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 0')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 300.0, 600.0),
|
||||
);
|
||||
expect(find.text('Group 0 Tile 1'), findsNothing);
|
||||
|
||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||
|
||||
const double scrollOffset = 19 * 300.0;
|
||||
@ -208,6 +252,10 @@ void main() {
|
||||
expect(controller.offset, scrollOffset);
|
||||
expect(find.text('Group 0 Tile 18'), findsNothing);
|
||||
expect(find.text('Group 0 Tile 19'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 0 Tile 19')),
|
||||
const Rect.fromLTRB(0.0, 0.0, 300.0, 600.0),
|
||||
);
|
||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||
|
||||
const double scrollOffset2 = 20 * 300.0;
|
||||
@ -215,6 +263,10 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Group 0 Tile 19'), findsNothing);
|
||||
expect(find.text('Group 1 Tile 0'), findsOneWidget);
|
||||
expect(
|
||||
tester.getRect(find.text('Group 1 Tile 0')),
|
||||
const Rect.fromLTRB(100.0, 0.0, 300.0, 600.0),
|
||||
);
|
||||
|
||||
final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
|
||||
final RenderSliverList first = renderSlivers[0];
|
||||
|
Loading…
Reference in New Issue
Block a user