Optionally show the text field length but not the max (#24183)

If maxLength is set to TextField.noMaxLength then continue to show the character counter but do not display the max input length value.
This commit is contained in:
S McDowall 2018-11-14 19:04:39 -05:00 committed by Hans Muller
parent 779c68f691
commit 87156df6d9
2 changed files with 44 additions and 16 deletions

View file

@ -78,7 +78,10 @@ class TextField extends StatefulWidget {
/// number of characters allowed in the text field is not restricted. If
/// [maxLength] is set, a character counter will be displayed below the
/// field, showing how many characters have been entered and how many are
/// allowed. After [maxLength] characters have been input, additional input
/// allowed unless the value is set to [noMaxLength] in which case only the
/// current length is displayed.
///
/// After [maxLength] characters have been input, additional input
/// is ignored, unless [maxLengthEnforced] is set to false. The TextField
/// enforces the length with a [LengthLimitingTextInputFormatter], which is
/// evaluated after the supplied [inputFormatters], if any. The [maxLength]
@ -192,6 +195,10 @@ class TextField extends StatefulWidget {
/// {@macro flutter.widgets.editableText.maxLines}
final int maxLines;
/// If [maxLength] is set to this value, only the "current input length"
/// part of the character counter is shown.
static const int noMaxLength = 9007199254740992; // math.pow(2, 53);
/// The maximum number of characters (Unicode scalar values) to allow in the
/// text field.
///
@ -339,9 +346,16 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
return effectiveDecoration;
final int currentLength = _effectiveController.value.text.runes.length;
final String counterText = '$currentLength/${widget.maxLength}';
final int remaining = (widget.maxLength - currentLength).clamp(0, widget.maxLength);
final String semanticCounterText = localizations.remainingTextFieldCharacterCount(remaining);
String counterText = '$currentLength';
String semanticCounterText = '';
if (widget.maxLength != TextField.noMaxLength) {
counterText += '/${widget.maxLength}';
final int remaining = (widget.maxLength - currentLength).clamp(0, widget.maxLength);
semanticCounterText = localizations.remainingTextFieldCharacterCount(remaining);
}
// Handle length exceeds maxLength
if (_effectiveController.value.text.runes.length > widget.maxLength) {
final ThemeData themeData = Theme.of(context);
return effectiveDecoration.copyWith(

View file

@ -1790,16 +1790,14 @@ void main() {
testWidgets('setting maxLength shows counter', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Material(
child: DefaultTextStyle(
style: TextStyle(fontFamily: 'Ahem', fontSize: 10.0),
child: Center(
child: Center(
child: TextField(
maxLength: 10,
),
),
),
),
));
);
expect(find.text('0/10'), findsOneWidget);
@ -1809,22 +1807,41 @@ void main() {
expect(find.text('5/10'), findsOneWidget);
});
testWidgets(
'setting maxLength to TextField.noMaxLength shows only entered length',
(WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Material(
child: Center(
child: TextField(
maxLength: TextField.noMaxLength,
),
),
),
),
);
expect(find.text('0'), findsOneWidget);
await tester.enterText(find.byType(TextField), '01234');
await tester.pump();
expect(find.text('5'), findsOneWidget);
});
testWidgets('TextField identifies as text field in semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
const MaterialApp(
home: Material(
child: DefaultTextStyle(
style: TextStyle(fontFamily: 'Ahem', fontSize: 10.0),
child: Center(
child: Center(
child: TextField(
maxLength: 10,
),
),
),
),
),
);
expect(semantics, includesNodeWith(flags: <SemanticsFlag>[SemanticsFlag.isTextField]));
@ -3162,9 +3179,7 @@ void main() {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: DefaultTextStyle(
style: const TextStyle(fontSize: 12.0, fontFamily: 'Ahem'),
child: MediaQuery(
body: MediaQuery(
data: MediaQueryData.fromWindow(ui.window).copyWith(textScaleFactor: 4.0),
child: Center(
child: TextField(
@ -3175,7 +3190,6 @@ void main() {
),
),
),
),
);
await tester.tap(find.byType(TextField));