Prevent InputDecorator
from supplying its descendants with non-normalized constraints (#130460)
Fixes https://github.com/flutter/flutter/issues/129611
This commit is contained in:
parent
d0bb56f024
commit
fe7d01ffab
@ -964,7 +964,7 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
boxToBaseline[prefixIcon] = _layoutLineBox(prefixIcon, containerConstraints);
|
boxToBaseline[prefixIcon] = _layoutLineBox(prefixIcon, containerConstraints);
|
||||||
boxToBaseline[suffixIcon] = _layoutLineBox(suffixIcon, containerConstraints);
|
boxToBaseline[suffixIcon] = _layoutLineBox(suffixIcon, containerConstraints);
|
||||||
final BoxConstraints contentConstraints = containerConstraints.copyWith(
|
final BoxConstraints contentConstraints = containerConstraints.copyWith(
|
||||||
maxWidth: containerConstraints.maxWidth - contentPadding.horizontal,
|
maxWidth: math.max(0.0, containerConstraints.maxWidth - contentPadding.horizontal),
|
||||||
);
|
);
|
||||||
boxToBaseline[prefix] = _layoutLineBox(prefix, contentConstraints);
|
boxToBaseline[prefix] = _layoutLineBox(prefix, contentConstraints);
|
||||||
boxToBaseline[suffix] = _layoutLineBox(suffix, contentConstraints);
|
boxToBaseline[suffix] = _layoutLineBox(suffix, contentConstraints);
|
||||||
@ -1093,7 +1093,7 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
final double minContainerHeight = decoration.isDense! || decoration.isCollapsed || expands
|
final double minContainerHeight = decoration.isDense! || decoration.isCollapsed || expands
|
||||||
? 0.0
|
? 0.0
|
||||||
: kMinInteractiveDimension;
|
: kMinInteractiveDimension;
|
||||||
final double maxContainerHeight = boxConstraints.maxHeight - bottomHeight;
|
final double maxContainerHeight = math.max(0.0, boxConstraints.maxHeight - bottomHeight);
|
||||||
final double containerHeight = expands
|
final double containerHeight = expands
|
||||||
? maxContainerHeight
|
? maxContainerHeight
|
||||||
: math.min(math.max(contentHeight, minContainerHeight), maxContainerHeight);
|
: math.min(math.max(contentHeight, minContainerHeight), maxContainerHeight);
|
||||||
|
@ -158,7 +158,11 @@ TextStyle? getIconStyle(WidgetTester tester, IconData icon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
for (final bool useMaterial3 in <bool>[true, false]){
|
runAllTests(useMaterial3: true);
|
||||||
|
runAllTests(useMaterial3: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void runAllTests({ required bool useMaterial3 }) {
|
||||||
testWidgets('InputDecorator input/label text layout', (WidgetTester tester) async {
|
testWidgets('InputDecorator input/label text layout', (WidgetTester tester) async {
|
||||||
// The label appears above the input text
|
// The label appears above the input text
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@ -1796,7 +1800,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
theme: theme,
|
theme: theme,
|
||||||
home: Material(
|
home: Material(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -2011,9 +2015,9 @@ void main() {
|
|||||||
|
|
||||||
// Overall height for this InputDecorator is 48dps because the prefix icon's minimum size
|
// Overall height for this InputDecorator is 48dps because the prefix icon's minimum size
|
||||||
// is 48x48 and the rest of the elements only require 40dps:
|
// is 48x48 and the rest of the elements only require 40dps:
|
||||||
// 12 - top padding
|
// 12 - top padding
|
||||||
// 16 - input text (font size 16dps)
|
// 16 - input text (font size 16dps)
|
||||||
// 12 - bottom padding
|
// 12 - bottom padding
|
||||||
|
|
||||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
|
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
|
||||||
expect(tester.getSize(find.text('text')).height, 16.0);
|
expect(tester.getSize(find.text('text')).height, 16.0);
|
||||||
@ -2085,10 +2089,10 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Overall height for this InputDecorator is 48dps because the prefix icon's minimum size
|
// Overall height for this InputDecorator is 48dps because the prefix icon's minimum size
|
||||||
// is 48x48 and the rest of the elements only require 40dps:
|
// is 48x48 and the rest of the elements only require 40dps:
|
||||||
// 12 - top padding
|
// 12 - top padding
|
||||||
// 16 - input text (font size 16dps)
|
// 16 - input text (font size 16dps)
|
||||||
// 12 - bottom padding
|
// 12 - bottom padding
|
||||||
|
|
||||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
|
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
|
||||||
expect(tester.getSize(find.byKey(prefixKey)).height, 16.0);
|
expect(tester.getSize(find.byKey(prefixKey)).height, 16.0);
|
||||||
@ -2303,9 +2307,9 @@ void main() {
|
|||||||
|
|
||||||
// Overall height for this InputDecorator is 100dps because the prefix icon's size
|
// Overall height for this InputDecorator is 100dps because the prefix icon's size
|
||||||
// is 100x100 and the rest of the elements only require 40dps:
|
// is 100x100 and the rest of the elements only require 40dps:
|
||||||
// 12 - top padding
|
// 12 - top padding
|
||||||
// 16 - input text (font size 16dps)
|
// 16 - input text (font size 16dps)
|
||||||
// 12 - bottom padding
|
// 12 - bottom padding
|
||||||
|
|
||||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 100.0));
|
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 100.0));
|
||||||
expect(tester.getSize(find.byKey(prefixKey)).height, 100.0);
|
expect(tester.getSize(find.byKey(prefixKey)).height, 100.0);
|
||||||
@ -5487,7 +5491,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55317
|
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55317
|
||||||
|
|
||||||
testWidgets('OutlineInputBorder with BorderRadius.zero should draw a rectangular border', (WidgetTester tester) async {
|
testWidgets('OutlineInputBorder with BorderRadius.zero should draw a rectangular border', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/78855
|
// Regression test for https://github.com/flutter/flutter/issues/78855
|
||||||
const String labelText = 'Flutter';
|
const String labelText = 'Flutter';
|
||||||
|
|
||||||
@ -6546,5 +6550,29 @@ void main() {
|
|||||||
// The prefix is inside the decorator.
|
// The prefix is inside the decorator.
|
||||||
expect(decoratorRight, lessThanOrEqualTo(prefixRight));
|
expect(decoratorRight, lessThanOrEqualTo(prefixRight));
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
testWidgets('InputDecorator with counter does not crash when given a 0 size', (WidgetTester tester) async {
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/129611
|
||||||
|
const InputDecoration decoration = InputDecoration(
|
||||||
|
contentPadding: EdgeInsetsDirectional.all(99),
|
||||||
|
prefixIcon: Focus(child: Icon(Icons.search)),
|
||||||
|
counter: Text('COUNTER'),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Center(
|
||||||
|
child: SizedBox.square(
|
||||||
|
dimension: 0.0,
|
||||||
|
child: buildInputDecorator(
|
||||||
|
useMaterial3: useMaterial3,
|
||||||
|
decoration: decoration,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.byType(InputDecorator), findsOneWidget);
|
||||||
|
expect(tester.renderObject<RenderBox>(find.text('COUNTER')).size, Size.zero);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user