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(() {
|
assert(() {
|
||||||
if (child != null && maxPaintExtent.isInfinite) {
|
if (child != null && maxPaintExtent.isInfinite) {
|
||||||
throw FlutterError(
|
throw FlutterError(
|
||||||
'Unreachable sliver found, you may have a sliver behind '
|
'Unreachable sliver found, you may have a sliver following '
|
||||||
'a sliver with infinite extent. '
|
'a sliver with an infinite extent. '
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -327,12 +327,50 @@ class RenderSliverMainAxisGroup extends RenderSliver with ContainerRenderObjectM
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void paint(PaintingContext context, Offset offset) {
|
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) {
|
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) {
|
if (child.geometry!.visible) {
|
||||||
final SliverPhysicalParentData childParentData = child.parentData! as SliverPhysicalParentData;
|
context.paintChild(child, childOffset);
|
||||||
context.paintChild(child, offset + childParentData.paintOffset);
|
|
||||||
}
|
}
|
||||||
child = childBefore(child);
|
child = childBefore(child);
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,16 @@ void main() {
|
|||||||
expect(controller.offset, 0);
|
expect(controller.offset, 0);
|
||||||
|
|
||||||
expect(find.text('Group 0 Tile 0'), findsOneWidget);
|
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(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 0 Tile 2'), findsNothing);
|
||||||
|
|
||||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||||
|
|
||||||
const double scrollOffset = 19 * 300.0;
|
const double scrollOffset = 19 * 300.0;
|
||||||
@ -44,7 +51,15 @@ void main() {
|
|||||||
expect(controller.offset, scrollOffset);
|
expect(controller.offset, scrollOffset);
|
||||||
expect(find.text('Group 0 Tile 18'), findsNothing);
|
expect(find.text('Group 0 Tile 18'), findsNothing);
|
||||||
expect(find.text('Group 0 Tile 19'), findsOneWidget);
|
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(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 List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
|
||||||
final RenderSliverList first = renderSlivers[0];
|
final RenderSliverList first = renderSlivers[0];
|
||||||
@ -85,9 +100,16 @@ void main() {
|
|||||||
expect(controller.offset, 0);
|
expect(controller.offset, 0);
|
||||||
|
|
||||||
expect(find.text('Group 0 Tile 0'), findsOneWidget);
|
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(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 0 Tile 2'), findsNothing);
|
||||||
|
|
||||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||||
|
|
||||||
const double scrollOffset = 19 * 300.0;
|
const double scrollOffset = 19 * 300.0;
|
||||||
@ -97,7 +119,15 @@ void main() {
|
|||||||
expect(controller.offset, scrollOffset);
|
expect(controller.offset, scrollOffset);
|
||||||
expect(find.text('Group 0 Tile 18'), findsNothing);
|
expect(find.text('Group 0 Tile 18'), findsNothing);
|
||||||
expect(find.text('Group 0 Tile 19'), findsOneWidget);
|
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(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 List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
|
||||||
final RenderSliverList first = renderSlivers[0];
|
final RenderSliverList first = renderSlivers[0];
|
||||||
@ -138,8 +168,11 @@ void main() {
|
|||||||
expect(controller.offset, 0);
|
expect(controller.offset, 0);
|
||||||
|
|
||||||
expect(find.text('Group 0 Tile 0'), findsOneWidget);
|
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 0 Tile 1'), findsNothing);
|
||||||
|
|
||||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||||
|
|
||||||
const double scrollOffset = 19 * 300.0;
|
const double scrollOffset = 19 * 300.0;
|
||||||
@ -149,6 +182,10 @@ void main() {
|
|||||||
expect(controller.offset, scrollOffset);
|
expect(controller.offset, scrollOffset);
|
||||||
expect(find.text('Group 0 Tile 18'), findsNothing);
|
expect(find.text('Group 0 Tile 18'), findsNothing);
|
||||||
expect(find.text('Group 0 Tile 19'), findsOneWidget);
|
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);
|
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||||
|
|
||||||
const double scrollOffset2 = 20 * 300.0;
|
const double scrollOffset2 = 20 * 300.0;
|
||||||
@ -156,6 +193,10 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(find.text('Group 0 Tile 19'), findsNothing);
|
expect(find.text('Group 0 Tile 19'), findsNothing);
|
||||||
expect(find.text('Group 1 Tile 0'), findsOneWidget);
|
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 List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
|
||||||
final RenderSliverList first = renderSlivers[0];
|
final RenderSliverList first = renderSlivers[0];
|
||||||
@ -197,8 +238,11 @@ void main() {
|
|||||||
expect(controller.offset, 0);
|
expect(controller.offset, 0);
|
||||||
|
|
||||||
expect(find.text('Group 0 Tile 0'), findsOneWidget);
|
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 0 Tile 1'), findsNothing);
|
||||||
|
|
||||||
expect(find.text('Group 1 Tile 0'), findsNothing);
|
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||||
|
|
||||||
const double scrollOffset = 19 * 300.0;
|
const double scrollOffset = 19 * 300.0;
|
||||||
@ -208,6 +252,10 @@ void main() {
|
|||||||
expect(controller.offset, scrollOffset);
|
expect(controller.offset, scrollOffset);
|
||||||
expect(find.text('Group 0 Tile 18'), findsNothing);
|
expect(find.text('Group 0 Tile 18'), findsNothing);
|
||||||
expect(find.text('Group 0 Tile 19'), findsOneWidget);
|
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);
|
expect(find.text('Group 1 Tile 0'), findsNothing);
|
||||||
|
|
||||||
const double scrollOffset2 = 20 * 300.0;
|
const double scrollOffset2 = 20 * 300.0;
|
||||||
@ -215,6 +263,10 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(find.text('Group 0 Tile 19'), findsNothing);
|
expect(find.text('Group 0 Tile 19'), findsNothing);
|
||||||
expect(find.text('Group 1 Tile 0'), findsOneWidget);
|
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 List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
|
||||||
final RenderSliverList first = renderSlivers[0];
|
final RenderSliverList first = renderSlivers[0];
|
||||||
|
Loading…
Reference in New Issue
Block a user