diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart index 80091f42644..607e8ee63ae 100644 --- a/packages/flutter/lib/src/material/input_decorator.dart +++ b/packages/flutter/lib/src/material/input_decorator.dart @@ -1224,25 +1224,25 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin @override double computeMinIntrinsicWidth(double height) { return _minWidth(icon, height) - + contentPadding.left + + (prefixIcon != null ? 0.0 : (textDirection == TextDirection.ltr ? contentPadding.left : contentPadding.right)) + _minWidth(prefixIcon, height) + _minWidth(prefix, height) + math.max(_minWidth(input, height), _minWidth(hint, height)) + _minWidth(suffix, height) + _minWidth(suffixIcon, height) - + contentPadding.right; + + (suffixIcon != null ? 0.0 : (textDirection == TextDirection.ltr ? contentPadding.right : contentPadding.left)); } @override double computeMaxIntrinsicWidth(double height) { return _maxWidth(icon, height) - + contentPadding.left + + (prefixIcon != null ? 0.0 : (textDirection == TextDirection.ltr ? contentPadding.left : contentPadding.right)) + _maxWidth(prefixIcon, height) + _maxWidth(prefix, height) + math.max(_maxWidth(input, height), _maxWidth(hint, height)) + _maxWidth(suffix, height) + _maxWidth(suffixIcon, height) - + contentPadding.right; + + (suffixIcon != null ? 0.0 : (textDirection == TextDirection.ltr ? contentPadding.right : contentPadding.left)); } double _lineHeight(double width, List boxes) { diff --git a/packages/flutter/test/material/input_decorator_test.dart b/packages/flutter/test/material/input_decorator_test.dart index 081a1257964..d2ca395b643 100644 --- a/packages/flutter/test/material/input_decorator_test.dart +++ b/packages/flutter/test/material/input_decorator_test.dart @@ -26,6 +26,7 @@ Widget buildInputDecorator({ bool isFocused = false, bool isHovering = false, bool useMaterial3 = false, + bool useIntrinsicWidth = false, TextStyle? baseStyle, TextAlignVertical? textAlignVertical, VisualDensity? visualDensity, @@ -34,6 +35,21 @@ Widget buildInputDecorator({ style: TextStyle(fontSize: 16.0), ), }) { + Widget widget = InputDecorator( + expands: expands, + decoration: decoration, + isEmpty: isEmpty, + isFocused: isFocused, + isHovering: isHovering, + baseStyle: baseStyle, + textAlignVertical: textAlignVertical, + child: child, + ); + + if (useIntrinsicWidth) { + widget = IntrinsicWidth(child: widget); + } + return MaterialApp( theme: ThemeData(useMaterial3: false), home: Material( @@ -50,16 +66,7 @@ Widget buildInputDecorator({ alignment: Alignment.topLeft, child: Directionality( textDirection: textDirection, - child: InputDecorator( - expands: expands, - decoration: decoration, - isEmpty: isEmpty, - isFocused: isFocused, - isHovering: isHovering, - baseStyle: baseStyle, - textAlignVertical: textAlignVertical, - child: child, - ), + child: widget, ), ), ); @@ -6890,6 +6897,48 @@ testWidgetsWithLeakTracking('OutlineInputBorder with BorderRadius.zero should dr expect(decoratorRight, lessThanOrEqualTo(prefixRight)); }); + testWidgetsWithLeakTracking('instrinic width with prefixIcon/suffixIcon', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/137937 + for (final TextDirection direction in TextDirection.values) { + Future measureText(InputDecoration decoration) async { + await tester.pumpWidget( + buildInputDecorator( + useMaterial3: useMaterial3, + // isEmpty: false (default) + // isFocused: false (default) + decoration: decoration, + useIntrinsicWidth: true, + textDirection: direction, + ), + ); + await tester.pumpAndSettle(); + + expect(find.text('text'), findsOneWidget); + + return tester.renderObject(find.text('text')).size; + } + + const EdgeInsetsGeometry padding = EdgeInsetsDirectional.only(end: 24, start: 12); + + final Size textSizeWithoutIcons = await measureText(const InputDecoration( + contentPadding: padding, + )); + + final Size textSizeWithPrefixIcon = await measureText(const InputDecoration( + contentPadding: padding, + prefixIcon: Focus(child: Icon(Icons.search)), + )); + + final Size textSizeWithSuffixIcon = await measureText(const InputDecoration( + contentPadding: padding, + suffixIcon: Focus(child: Icon(Icons.search)), + )); + + expect(textSizeWithPrefixIcon.width, equals(textSizeWithoutIcons.width), reason: 'text width is different with prefixIcon and $direction'); + expect(textSizeWithSuffixIcon.width, equals(textSizeWithoutIcons.width), reason: 'text width is different with prefixIcon and $direction'); + } + }); + testWidgetsWithLeakTracking('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(