Skip to content

Commit ad62645

Browse files
authored
Fix intrinsic width of input decorator (#138074)
Fix min intrinsic width of input decorator by removing left or right padding when `prefixIcon` or `suffixIcon` are used. Fixes #137937.
1 parent e49cc81 commit ad62645

File tree

2 files changed

+63
-14
lines changed

2 files changed

+63
-14
lines changed

packages/flutter/lib/src/material/input_decorator.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,25 +1224,25 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
12241224
@override
12251225
double computeMinIntrinsicWidth(double height) {
12261226
return _minWidth(icon, height)
1227-
+ contentPadding.left
1227+
+ (prefixIcon != null ? 0.0 : (textDirection == TextDirection.ltr ? contentPadding.left : contentPadding.right))
12281228
+ _minWidth(prefixIcon, height)
12291229
+ _minWidth(prefix, height)
12301230
+ math.max(_minWidth(input, height), _minWidth(hint, height))
12311231
+ _minWidth(suffix, height)
12321232
+ _minWidth(suffixIcon, height)
1233-
+ contentPadding.right;
1233+
+ (suffixIcon != null ? 0.0 : (textDirection == TextDirection.ltr ? contentPadding.right : contentPadding.left));
12341234
}
12351235

12361236
@override
12371237
double computeMaxIntrinsicWidth(double height) {
12381238
return _maxWidth(icon, height)
1239-
+ contentPadding.left
1239+
+ (prefixIcon != null ? 0.0 : (textDirection == TextDirection.ltr ? contentPadding.left : contentPadding.right))
12401240
+ _maxWidth(prefixIcon, height)
12411241
+ _maxWidth(prefix, height)
12421242
+ math.max(_maxWidth(input, height), _maxWidth(hint, height))
12431243
+ _maxWidth(suffix, height)
12441244
+ _maxWidth(suffixIcon, height)
1245-
+ contentPadding.right;
1245+
+ (suffixIcon != null ? 0.0 : (textDirection == TextDirection.ltr ? contentPadding.right : contentPadding.left));
12461246
}
12471247

12481248
double _lineHeight(double width, List<RenderBox?> boxes) {

packages/flutter/test/material/input_decorator_test.dart

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Widget buildInputDecorator({
2626
bool isFocused = false,
2727
bool isHovering = false,
2828
bool useMaterial3 = false,
29+
bool useIntrinsicWidth = false,
2930
TextStyle? baseStyle,
3031
TextAlignVertical? textAlignVertical,
3132
VisualDensity? visualDensity,
@@ -34,6 +35,21 @@ Widget buildInputDecorator({
3435
style: TextStyle(fontSize: 16.0),
3536
),
3637
}) {
38+
Widget widget = InputDecorator(
39+
expands: expands,
40+
decoration: decoration,
41+
isEmpty: isEmpty,
42+
isFocused: isFocused,
43+
isHovering: isHovering,
44+
baseStyle: baseStyle,
45+
textAlignVertical: textAlignVertical,
46+
child: child,
47+
);
48+
49+
if (useIntrinsicWidth) {
50+
widget = IntrinsicWidth(child: widget);
51+
}
52+
3753
return MaterialApp(
3854
theme: ThemeData(useMaterial3: false),
3955
home: Material(
@@ -50,16 +66,7 @@ Widget buildInputDecorator({
5066
alignment: Alignment.topLeft,
5167
child: Directionality(
5268
textDirection: textDirection,
53-
child: InputDecorator(
54-
expands: expands,
55-
decoration: decoration,
56-
isEmpty: isEmpty,
57-
isFocused: isFocused,
58-
isHovering: isHovering,
59-
baseStyle: baseStyle,
60-
textAlignVertical: textAlignVertical,
61-
child: child,
62-
),
69+
child: widget,
6370
),
6471
),
6572
);
@@ -6890,6 +6897,48 @@ testWidgetsWithLeakTracking('OutlineInputBorder with BorderRadius.zero should dr
68906897
expect(decoratorRight, lessThanOrEqualTo(prefixRight));
68916898
});
68926899

6900+
testWidgetsWithLeakTracking('instrinic width with prefixIcon/suffixIcon', (WidgetTester tester) async {
6901+
// Regression test for https://github.com/flutter/flutter/issues/137937
6902+
for (final TextDirection direction in TextDirection.values) {
6903+
Future<Size> measureText(InputDecoration decoration) async {
6904+
await tester.pumpWidget(
6905+
buildInputDecorator(
6906+
useMaterial3: useMaterial3,
6907+
// isEmpty: false (default)
6908+
// isFocused: false (default)
6909+
decoration: decoration,
6910+
useIntrinsicWidth: true,
6911+
textDirection: direction,
6912+
),
6913+
);
6914+
await tester.pumpAndSettle();
6915+
6916+
expect(find.text('text'), findsOneWidget);
6917+
6918+
return tester.renderObject<RenderBox>(find.text('text')).size;
6919+
}
6920+
6921+
const EdgeInsetsGeometry padding = EdgeInsetsDirectional.only(end: 24, start: 12);
6922+
6923+
final Size textSizeWithoutIcons = await measureText(const InputDecoration(
6924+
contentPadding: padding,
6925+
));
6926+
6927+
final Size textSizeWithPrefixIcon = await measureText(const InputDecoration(
6928+
contentPadding: padding,
6929+
prefixIcon: Focus(child: Icon(Icons.search)),
6930+
));
6931+
6932+
final Size textSizeWithSuffixIcon = await measureText(const InputDecoration(
6933+
contentPadding: padding,
6934+
suffixIcon: Focus(child: Icon(Icons.search)),
6935+
));
6936+
6937+
expect(textSizeWithPrefixIcon.width, equals(textSizeWithoutIcons.width), reason: 'text width is different with prefixIcon and $direction');
6938+
expect(textSizeWithSuffixIcon.width, equals(textSizeWithoutIcons.width), reason: 'text width is different with prefixIcon and $direction');
6939+
}
6940+
});
6941+
68936942
testWidgetsWithLeakTracking('InputDecorator with counter does not crash when given a 0 size', (WidgetTester tester) async {
68946943
// Regression test for https://github.com/flutter/flutter/issues/129611
68956944
const InputDecoration decoration = InputDecoration(

0 commit comments

Comments
 (0)