Unverified Commit 9e0ad9b6 authored by Andre's avatar Andre Committed by GitHub

Fix FittedBox BoxFit.scaleDown sizing (#63668)

parent 654022ae
......@@ -2352,6 +2352,15 @@ class RenderFittedBox extends RenderProxyBox {
markNeedsPaint();
}
bool _fitAffectsLayout(BoxFit fit) {
switch (fit) {
case BoxFit.scaleDown:
return true;
default:
return false;
}
}
/// How to inscribe the child into the space allocated during layout.
BoxFit get fit => _fit;
BoxFit _fit;
......@@ -2359,9 +2368,14 @@ class RenderFittedBox extends RenderProxyBox {
assert(value != null);
if (_fit == value)
return;
final BoxFit lastFit = _fit;
_fit = value;
_clearPaintData();
markNeedsPaint();
if (_fitAffectsLayout(lastFit) || _fitAffectsLayout(value)) {
markNeedsLayout();
} else {
_clearPaintData();
markNeedsPaint();
}
}
/// How to align the child within its parent's bounds.
......@@ -2403,7 +2417,16 @@ class RenderFittedBox extends RenderProxyBox {
void performLayout() {
if (child != null) {
child.layout(const BoxConstraints(), parentUsesSize: true);
size = constraints.constrainSizeAndAttemptToPreserveAspectRatio(child.size);
switch (fit) {
case BoxFit.scaleDown:
final BoxConstraints sizeConstraints = constraints.loosen();
final Size unconstrainedSize = sizeConstraints.constrainSizeAndAttemptToPreserveAspectRatio(child.size);
size = constraints.constrain(unconstrainedSize);
break;
default:
size = constraints.constrainSizeAndAttemptToPreserveAspectRatio(child.size);
break;
}
_clearPaintData();
} else {
size = constraints.smallest;
......
......@@ -486,6 +486,111 @@ void main() {
await tester.pumpWidget(FittedBox(fit: BoxFit.none, child: Container(), clipBehavior: Clip.antiAlias));
expect(renderObject.clipBehavior, equals(Clip.antiAlias));
});
testWidgets('BoxFit.scaleDown matches size of child', (WidgetTester tester) async {
final Key outside = UniqueKey();
final Key inside = UniqueKey();
// Does not scale up when child is smaller than constraints
await tester.pumpWidget(
Center(
child: Container(
width: 200.0,
child: FittedBox(
key: outside,
fit: BoxFit.scaleDown,
child: Container(
key: inside,
width: 100.0,
height: 50.0,
),
),
),
),
);
final RenderBox outsideBox = tester.firstRenderObject(find.byKey(outside));
final RenderBox insideBox = tester.firstRenderObject(find.byKey(inside));
expect(outsideBox.size.width, 200.0);
expect(outsideBox.size.height, 50.0);
Offset outsidePoint = outsideBox.localToGlobal(Offset.zero);
Offset insidePoint = insideBox.localToGlobal(Offset.zero);
expect(insidePoint - outsidePoint, equals(const Offset(50.0, 0.0)));
// Scales down when child is bigger than constraints
await tester.pumpWidget(
Center(
child: Container(
width: 200.0,
child: FittedBox(
key: outside,
fit: BoxFit.scaleDown,
child: Container(
key: inside,
width: 400.0,
height: 200.0,
),
),
),
),
);
expect(outsideBox.size.width, 200.0);
expect(outsideBox.size.height, 100.0);
outsidePoint = outsideBox.localToGlobal(Offset.zero);
insidePoint = insideBox.localToGlobal(Offset.zero);
expect(insidePoint - outsidePoint, equals(Offset.zero));
});
testWidgets('Switching to and from BoxFit.scaleDown causes relayout', (WidgetTester tester) async {
final Key outside = UniqueKey();
final Widget scaleDownWidget = Center(
child: Container(
width: 200.0,
child: FittedBox(
key: outside,
fit: BoxFit.scaleDown,
child: Container(
width: 100.0,
height: 50.0,
),
),
),
);
final Widget coverWidget = Center(
child: Container(
width: 200.0,
child: FittedBox(
key: outside,
child: Container(
width: 100.0,
height: 50.0,
),
),
),
);
await tester.pumpWidget(scaleDownWidget);
final RenderBox outsideBox = tester.firstRenderObject(find.byKey(outside));
expect(outsideBox.size.height, 50.0);
await tester.pumpWidget(coverWidget);
expect(outsideBox.size.height, 100.0);
await tester.pumpWidget(scaleDownWidget);
expect(outsideBox.size.height, 50.0);
});
}
List<Type> getLayers() {
......
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