diff --git a/packages/flutter/lib/src/cupertino/text_field.dart b/packages/flutter/lib/src/cupertino/text_field.dart index f69a235ccf4..3473130fce5 100644 --- a/packages/flutter/lib/src/cupertino/text_field.dart +++ b/packages/flutter/lib/src/cupertino/text_field.dart @@ -878,13 +878,13 @@ class _CupertinoTextFieldState extends State with Restoratio super.build(context); // See AutomaticKeepAliveClientMixin. assert(debugCheckHasDirectionality(context)); final TextEditingController controller = _effectiveController; - final List formatters = widget.inputFormatters ?? []; final TextSelectionControls textSelectionControls = widget.selectionControls ?? cupertinoTextSelectionControls; final bool enabled = widget.enabled ?? true; final Offset cursorOffset = Offset(_iOSHorizontalCursorOffsetPixels / MediaQuery.of(context).devicePixelRatio, 0); - if (widget.maxLength != null && widget.maxLengthEnforced) { - formatters.add(LengthLimitingTextInputFormatter(widget.maxLength)); - } + final List formatters = [ + ...?widget.inputFormatters, + if (widget.maxLength != null && widget.maxLengthEnforced) LengthLimitingTextInputFormatter(widget.maxLength) + ]; final CupertinoThemeData themeData = CupertinoTheme.of(context); final TextStyle? resolvedStyle = widget.style?.copyWith( diff --git a/packages/flutter/lib/src/material/text_field.dart b/packages/flutter/lib/src/material/text_field.dart index 729634bff21..3b4a00aaedd 100644 --- a/packages/flutter/lib/src/material/text_field.dart +++ b/packages/flutter/lib/src/material/text_field.dart @@ -1261,9 +1261,10 @@ class _TextFieldState extends State with RestorationMixin implements final Brightness keyboardAppearance = widget.keyboardAppearance ?? theme.primaryColorBrightness; final TextEditingController controller = _effectiveController; final FocusNode focusNode = _effectiveFocusNode; - final List formatters = widget.inputFormatters ?? []; - if (widget.maxLength != null && widget.maxLengthEnforced) - formatters.add(LengthLimitingTextInputFormatter(widget.maxLength)); + final List formatters = [ + ...?widget.inputFormatters, + if (widget.maxLength != null && widget.maxLengthEnforced) LengthLimitingTextInputFormatter(widget.maxLength) + ]; TextSelectionControls? textSelectionControls = widget.selectionControls; final bool paintCursorAboveText; diff --git a/packages/flutter/test/cupertino/text_field_test.dart b/packages/flutter/test/cupertino/text_field_test.dart index 452408a2c33..6564044a250 100644 --- a/packages/flutter/test/cupertino/text_field_test.dart +++ b/packages/flutter/test/cupertino/text_field_test.dart @@ -4289,4 +4289,16 @@ void main() { final EditableText widget = tester.widget(find.byType(EditableText)); expect(widget.selectionControls, equals(selectionControl)); }); + + testWidgets('Do not add LengthLimiting formatter to the user supplied list', (WidgetTester tester) async { + final List formatters = []; + + await tester.pumpWidget( + CupertinoApp( + home: CupertinoTextField(maxLength: 5, inputFormatters: formatters), + ) + ); + + expect(formatters.isEmpty, isTrue); + }); } diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart index f7f50a41b34..fce098fb330 100644 --- a/packages/flutter/test/material/text_field_test.dart +++ b/packages/flutter/test/material/text_field_test.dart @@ -3344,6 +3344,22 @@ void main() { expect(textController.text, '145623'); }); + testWidgets('Do not add LengthLimiting formatter to the user supplied list', (WidgetTester tester) async { + final List formatters = []; + + await tester.pumpWidget( + overlay( + child: TextField( + decoration: null, + maxLength: 5, + inputFormatters: formatters, + ), + ), + ); + + expect(formatters.isEmpty, isTrue); + }); + testWidgets('Text field scrolls the caret into view', (WidgetTester tester) async { final TextEditingController controller = TextEditingController();