Make FittedBox not throw when child has zero size. (#150430)

fix https://github.com/flutter/flutter/issues/135082 , fix https://github.com/flutter/flutter/issues/139539 , fix https://github.com/flutter/flutter/issues/142910

Before, `FittedBox` would throw when child size is zero, unless the constraint is tight and fit is not `BoxFit.scaleDown`.
This commit is contained in:
PurplePolyhedron 2024-07-09 08:51:04 +10:00 committed by GitHub
parent a3c7094d7d
commit f194cd3298
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 20 deletions

View File

@ -322,10 +322,12 @@ class BoxConstraints extends Constraints {
return result;
}
if (size.isEmpty) {
return constrain(size);
}
double width = size.width;
double height = size.height;
assert(width > 0.0);
assert(height > 0.0);
final double aspectRatio = width / height;
if (width > maxWidth) {

View File

@ -2711,24 +2711,6 @@ class RenderFittedBox extends RenderProxyBox {
if (child != null) {
final Size childSize = child!.getDryLayout(const BoxConstraints());
// During [RenderObject.debugCheckingIntrinsics] a child that doesn't
// support dry layout may provide us with an invalid size that triggers
// assertions if we try to work with it. Instead of throwing, we bail
// out early in that case.
bool invalidChildSize = false;
assert(() {
if (RenderObject.debugCheckingIntrinsics && childSize.width * childSize.height == 0.0) {
invalidChildSize = true;
}
return true;
}());
if (invalidChildSize) {
assert(debugCannotComputeDryLayout(
reason: 'Child provided invalid size of $childSize.',
));
return Size.zero;
}
switch (fit) {
case BoxFit.scaleDown:
final BoxConstraints sizeConstraints = constraints.loosen();

View File

@ -182,4 +182,17 @@ void main() {
expect(constraints, const BoxConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4));
});
test('BoxConstraints.constrainSizeAndAttemptToPreserveAspectRatio can handle empty size', () {
const BoxConstraints constraints = BoxConstraints(
minWidth: 10.0,
maxWidth: 20.0,
minHeight: 10.0,
maxHeight: 20.0,
);
const Size unconstrainedSize = Size(15.0, 0.0);
final Size constrainedSize = constraints.constrainSizeAndAttemptToPreserveAspectRatio(
unconstrainedSize,
);
expect(constrainedSize, const Size(15.0, 10.0));
});
}

View File

@ -605,6 +605,38 @@ void main() {
await tester.tap(find.byType(FittedBox), warnIfMissed: false);
expect(tester.takeException(), isNull);
});
// Regression test for https://github.com/flutter/flutter/issues/135082
testWidgets('FittedBox with zero size child does not throw', (WidgetTester tester) async {
await tester.pumpWidget(
const Center(
child: SizedBox(
height: 200.0,
width: 200.0,
child: FittedBox(
fit: BoxFit.scaleDown,
child: SizedBox.shrink(),
),
),
),
);
expect(tester.takeException(), isNull);
await tester.pumpWidget(
Center(
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 200.0,
maxHeight: 200.0,
),
child: const FittedBox(
child: SizedBox.shrink(),
),
),
),
);
expect(tester.takeException(), isNull);
});
}
List<Type> getLayers() {