Unverified Commit 6e888dac authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Add enableSuggestions flag to TextField and TextFormField (#42550)

This flag controls Android's keyboard suggestions on/off
parent 98bc378d
...@@ -197,8 +197,8 @@ class CupertinoTextField extends StatefulWidget { ...@@ -197,8 +197,8 @@ class CupertinoTextField extends StatefulWidget {
/// ///
/// The [autocorrect], [autofocus], [clearButtonMode], [dragStartBehavior], /// The [autocorrect], [autofocus], [clearButtonMode], [dragStartBehavior],
/// [expands], [maxLengthEnforced], [obscureText], [prefixMode], [readOnly], /// [expands], [maxLengthEnforced], [obscureText], [prefixMode], [readOnly],
/// [scrollPadding], [suffixMode], and [textAlign] properties must not be /// [scrollPadding], [suffixMode], [textAlign], and [enableSuggestions] properties
/// null. /// must not be null.
/// ///
/// See also: /// See also:
/// ///
...@@ -235,6 +235,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -235,6 +235,7 @@ class CupertinoTextField extends StatefulWidget {
this.autofocus = false, this.autofocus = false,
this.obscureText = false, this.obscureText = false,
this.autocorrect = true, this.autocorrect = true,
this.enableSuggestions = true,
this.maxLines = 1, this.maxLines = 1,
this.minLines, this.minLines,
this.expands = false, this.expands = false,
...@@ -260,6 +261,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -260,6 +261,7 @@ class CupertinoTextField extends StatefulWidget {
assert(autofocus != null), assert(autofocus != null),
assert(obscureText != null), assert(obscureText != null),
assert(autocorrect != null), assert(autocorrect != null),
assert(enableSuggestions != null),
assert(maxLengthEnforced != null), assert(maxLengthEnforced != null),
assert(scrollPadding != null), assert(scrollPadding != null),
assert(dragStartBehavior != null), assert(dragStartBehavior != null),
...@@ -415,6 +417,9 @@ class CupertinoTextField extends StatefulWidget { ...@@ -415,6 +417,9 @@ class CupertinoTextField extends StatefulWidget {
/// {@macro flutter.widgets.editableText.autocorrect} /// {@macro flutter.widgets.editableText.autocorrect}
final bool autocorrect; final bool autocorrect;
/// {@macro flutter.services.textInput.enableSuggestions}
final bool enableSuggestions;
/// {@macro flutter.widgets.editableText.maxLines} /// {@macro flutter.widgets.editableText.maxLines}
final int maxLines; final int maxLines;
...@@ -561,7 +566,8 @@ class CupertinoTextField extends StatefulWidget { ...@@ -561,7 +566,8 @@ class CupertinoTextField extends StatefulWidget {
properties.add(DiagnosticsProperty<TextStyle>('style', style, defaultValue: null)); properties.add(DiagnosticsProperty<TextStyle>('style', style, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true));
properties.add(DiagnosticsProperty<bool>('enableSuggestions', enableSuggestions, defaultValue: true));
properties.add(IntProperty('maxLines', maxLines, defaultValue: 1)); properties.add(IntProperty('maxLines', maxLines, defaultValue: 1));
properties.add(IntProperty('minLines', minLines, defaultValue: null)); properties.add(IntProperty('minLines', minLines, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false));
...@@ -877,6 +883,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK ...@@ -877,6 +883,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
autofocus: widget.autofocus, autofocus: widget.autofocus,
obscureText: widget.obscureText, obscureText: widget.obscureText,
autocorrect: widget.autocorrect, autocorrect: widget.autocorrect,
enableSuggestions: widget.enableSuggestions,
maxLines: widget.maxLines, maxLines: widget.maxLines,
minLines: widget.minLines, minLines: widget.minLines,
expands: widget.expands, expands: widget.expands,
......
...@@ -277,8 +277,8 @@ class TextField extends StatefulWidget { ...@@ -277,8 +277,8 @@ class TextField extends StatefulWidget {
/// is null (the default) and [readOnly] is true. /// is null (the default) and [readOnly] is true.
/// ///
/// The [textAlign], [autofocus], [obscureText], [readOnly], [autocorrect], /// The [textAlign], [autofocus], [obscureText], [readOnly], [autocorrect],
/// [maxLengthEnforced], [scrollPadding], [maxLines], and [maxLength] /// [maxLengthEnforced], [scrollPadding], [maxLines], [maxLength], and
/// arguments must not be null. /// [enableSuggestions] arguments must not be null.
/// ///
/// See also: /// See also:
/// ///
...@@ -303,6 +303,7 @@ class TextField extends StatefulWidget { ...@@ -303,6 +303,7 @@ class TextField extends StatefulWidget {
this.autofocus = false, this.autofocus = false,
this.obscureText = false, this.obscureText = false,
this.autocorrect = true, this.autocorrect = true,
this.enableSuggestions = true,
this.maxLines = 1, this.maxLines = 1,
this.minLines, this.minLines,
this.expands = false, this.expands = false,
...@@ -329,6 +330,7 @@ class TextField extends StatefulWidget { ...@@ -329,6 +330,7 @@ class TextField extends StatefulWidget {
assert(autofocus != null), assert(autofocus != null),
assert(obscureText != null), assert(obscureText != null),
assert(autocorrect != null), assert(autocorrect != null),
assert(enableSuggestions != null),
assert(enableInteractiveSelection != null), assert(enableInteractiveSelection != null),
assert(maxLengthEnforced != null), assert(maxLengthEnforced != null),
assert(scrollPadding != null), assert(scrollPadding != null),
...@@ -454,6 +456,9 @@ class TextField extends StatefulWidget { ...@@ -454,6 +456,9 @@ class TextField extends StatefulWidget {
/// {@macro flutter.widgets.editableText.autocorrect} /// {@macro flutter.widgets.editableText.autocorrect}
final bool autocorrect; final bool autocorrect;
/// {@macro flutter.services.textInput.enableSuggestions}
final bool enableSuggestions;
/// {@macro flutter.widgets.editableText.maxLines} /// {@macro flutter.widgets.editableText.maxLines}
final int maxLines; final int maxLines;
...@@ -676,6 +681,7 @@ class TextField extends StatefulWidget { ...@@ -676,6 +681,7 @@ class TextField extends StatefulWidget {
properties.add(DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true)); properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true));
properties.add(DiagnosticsProperty<bool>('enableSuggestions', enableSuggestions, defaultValue: true));
properties.add(IntProperty('maxLines', maxLines, defaultValue: 1)); properties.add(IntProperty('maxLines', maxLines, defaultValue: 1));
properties.add(IntProperty('minLines', minLines, defaultValue: null)); properties.add(IntProperty('minLines', minLines, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false));
...@@ -955,6 +961,7 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe ...@@ -955,6 +961,7 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe
autofocus: widget.autofocus, autofocus: widget.autofocus,
obscureText: widget.obscureText, obscureText: widget.obscureText,
autocorrect: widget.autocorrect, autocorrect: widget.autocorrect,
enableSuggestions: widget.enableSuggestions,
maxLines: widget.maxLines, maxLines: widget.maxLines,
minLines: widget.minLines, minLines: widget.minLines,
expands: widget.expands, expands: widget.expands,
......
...@@ -98,6 +98,7 @@ class TextFormField extends FormField<String> { ...@@ -98,6 +98,7 @@ class TextFormField extends FormField<String> {
bool showCursor, bool showCursor,
bool obscureText = false, bool obscureText = false,
bool autocorrect = true, bool autocorrect = true,
bool enableSuggestions = true,
bool autovalidate = false, bool autovalidate = false,
bool maxLengthEnforced = true, bool maxLengthEnforced = true,
int maxLines = 1, int maxLines = 1,
...@@ -125,6 +126,7 @@ class TextFormField extends FormField<String> { ...@@ -125,6 +126,7 @@ class TextFormField extends FormField<String> {
assert(readOnly != null), assert(readOnly != null),
assert(obscureText != null), assert(obscureText != null),
assert(autocorrect != null), assert(autocorrect != null),
assert(enableSuggestions != null),
assert(autovalidate != null), assert(autovalidate != null),
assert(maxLengthEnforced != null), assert(maxLengthEnforced != null),
assert(scrollPadding != null), assert(scrollPadding != null),
...@@ -177,6 +179,7 @@ class TextFormField extends FormField<String> { ...@@ -177,6 +179,7 @@ class TextFormField extends FormField<String> {
showCursor: showCursor, showCursor: showCursor,
obscureText: obscureText, obscureText: obscureText,
autocorrect: autocorrect, autocorrect: autocorrect,
enableSuggestions: enableSuggestions,
maxLengthEnforced: maxLengthEnforced, maxLengthEnforced: maxLengthEnforced,
maxLines: maxLines, maxLines: maxLines,
minLines: minLines, minLines: minLines,
......
...@@ -386,6 +386,7 @@ class TextInputConfiguration { ...@@ -386,6 +386,7 @@ class TextInputConfiguration {
this.inputType = TextInputType.text, this.inputType = TextInputType.text,
this.obscureText = false, this.obscureText = false,
this.autocorrect = true, this.autocorrect = true,
this.enableSuggestions = true,
this.actionLabel, this.actionLabel,
this.inputAction = TextInputAction.done, this.inputAction = TextInputAction.done,
this.keyboardAppearance = Brightness.light, this.keyboardAppearance = Brightness.light,
...@@ -393,6 +394,7 @@ class TextInputConfiguration { ...@@ -393,6 +394,7 @@ class TextInputConfiguration {
}) : assert(inputType != null), }) : assert(inputType != null),
assert(obscureText != null), assert(obscureText != null),
assert(autocorrect != null), assert(autocorrect != null),
assert(enableSuggestions != null),
assert(keyboardAppearance != null), assert(keyboardAppearance != null),
assert(inputAction != null), assert(inputAction != null),
assert(textCapitalization != null); assert(textCapitalization != null);
...@@ -410,6 +412,20 @@ class TextInputConfiguration { ...@@ -410,6 +412,20 @@ class TextInputConfiguration {
/// Defaults to true. /// Defaults to true.
final bool autocorrect; final bool autocorrect;
/// {@template flutter.services.textInput.enableSuggestions}
/// Whether to show input suggestions as the user types.
///
/// This flag only affects Android. On iOS, suggestions are tied directly to
/// [autocorrect], so that suggestions are only shown when [autocorrect] is
/// true. On Android autocorrection and suggestion are controlled separately.
///
/// Defaults to true. Cannot be null.
///
/// See also:
/// * <https://developer.android.com/reference/android/text/InputType.html#TYPE_TEXT_FLAG_NO_SUGGESTIONS>
/// {@endtemplate}
final bool enableSuggestions;
/// What text to display in the text input control's action button. /// What text to display in the text input control's action button.
final String actionLabel; final String actionLabel;
...@@ -439,6 +455,7 @@ class TextInputConfiguration { ...@@ -439,6 +455,7 @@ class TextInputConfiguration {
'inputType': inputType.toJson(), 'inputType': inputType.toJson(),
'obscureText': obscureText, 'obscureText': obscureText,
'autocorrect': autocorrect, 'autocorrect': autocorrect,
'enableSuggestions': enableSuggestions,
'actionLabel': actionLabel, 'actionLabel': actionLabel,
'inputAction': inputAction.toString(), 'inputAction': inputAction.toString(),
'textCapitalization': textCapitalization.toString(), 'textCapitalization': textCapitalization.toString(),
......
...@@ -342,9 +342,9 @@ class EditableText extends StatefulWidget { ...@@ -342,9 +342,9 @@ class EditableText extends StatefulWidget {
/// The [controller], [focusNode], [obscureText], [autocorrect], [autofocus], /// The [controller], [focusNode], [obscureText], [autocorrect], [autofocus],
/// [showSelectionHandles], [enableInteractiveSelection], [forceLine], /// [showSelectionHandles], [enableInteractiveSelection], [forceLine],
/// [style], [cursorColor], [cursorOpacityAnimates],[backgroundCursorColor], /// [style], [cursorColor], [cursorOpacityAnimates],[backgroundCursorColor],
/// [paintCursorAboveText], [textAlign], [dragStartBehavior], [scrollPadding], /// [enableSuggestions], [paintCursorAboveText], [textAlign], [dragStartBehavior],
/// [dragStartBehavior], [toolbarOptions], [rendererIgnoresPointer], and /// [scrollPadding], [dragStartBehavior], [toolbarOptions],
/// [readOnly] arguments must not be null. /// [rendererIgnoresPointer], and [readOnly] arguments must not be null.
EditableText({ EditableText({
Key key, Key key,
@required this.controller, @required this.controller,
...@@ -352,6 +352,7 @@ class EditableText extends StatefulWidget { ...@@ -352,6 +352,7 @@ class EditableText extends StatefulWidget {
this.readOnly = false, this.readOnly = false,
this.obscureText = false, this.obscureText = false,
this.autocorrect = true, this.autocorrect = true,
this.enableSuggestions = true,
@required this.style, @required this.style,
StrutStyle strutStyle, StrutStyle strutStyle,
@required this.cursorColor, @required this.cursorColor,
...@@ -401,6 +402,7 @@ class EditableText extends StatefulWidget { ...@@ -401,6 +402,7 @@ class EditableText extends StatefulWidget {
assert(focusNode != null), assert(focusNode != null),
assert(obscureText != null), assert(obscureText != null),
assert(autocorrect != null), assert(autocorrect != null),
assert(enableSuggestions != null),
assert(showSelectionHandles != null), assert(showSelectionHandles != null),
assert(enableInteractiveSelection != null), assert(enableInteractiveSelection != null),
assert(readOnly != null), assert(readOnly != null),
...@@ -515,6 +517,9 @@ class EditableText extends StatefulWidget { ...@@ -515,6 +517,9 @@ class EditableText extends StatefulWidget {
/// {@endtemplate} /// {@endtemplate}
final bool autocorrect; final bool autocorrect;
/// {@macro flutter.services.textInput.enableSuggestions}
final bool enableSuggestions;
/// The text style to use for the editable text. /// The text style to use for the editable text.
final TextStyle style; final TextStyle style;
...@@ -1037,6 +1042,7 @@ class EditableText extends StatefulWidget { ...@@ -1037,6 +1042,7 @@ class EditableText extends StatefulWidget {
properties.add(DiagnosticsProperty<FocusNode>('focusNode', focusNode)); properties.add(DiagnosticsProperty<FocusNode>('focusNode', focusNode));
properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true)); properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true));
properties.add(DiagnosticsProperty<bool>('enableSuggestions', enableSuggestions, defaultValue: true));
style?.debugFillProperties(properties); style?.debugFillProperties(properties);
properties.add(EnumProperty<TextAlign>('textAlign', textAlign, defaultValue: null)); properties.add(EnumProperty<TextAlign>('textAlign', textAlign, defaultValue: null));
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null)); properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
...@@ -1394,6 +1400,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -1394,6 +1400,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
inputType: widget.keyboardType, inputType: widget.keyboardType,
obscureText: widget.obscureText, obscureText: widget.obscureText,
autocorrect: widget.autocorrect, autocorrect: widget.autocorrect,
enableSuggestions: widget.enableSuggestions,
inputAction: widget.textInputAction ?? (widget.keyboardType == TextInputType.multiline inputAction: widget.textInputAction ?? (widget.keyboardType == TextInputType.multiline
? TextInputAction.newline ? TextInputAction.newline
: TextInputAction.done : TextInputAction.done
...@@ -1842,6 +1849,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -1842,6 +1849,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
textWidthBasis: widget.textWidthBasis, textWidthBasis: widget.textWidthBasis,
obscureText: widget.obscureText, obscureText: widget.obscureText,
autocorrect: widget.autocorrect, autocorrect: widget.autocorrect,
enableSuggestions: widget.enableSuggestions,
offset: offset, offset: offset,
onSelectionChanged: _handleSelectionChanged, onSelectionChanged: _handleSelectionChanged,
onCaretChanged: _handleCaretChanged, onCaretChanged: _handleCaretChanged,
...@@ -1907,6 +1915,7 @@ class _Editable extends LeafRenderObjectWidget { ...@@ -1907,6 +1915,7 @@ class _Editable extends LeafRenderObjectWidget {
this.locale, this.locale,
this.obscureText, this.obscureText,
this.autocorrect, this.autocorrect,
this.enableSuggestions,
this.offset, this.offset,
this.onSelectionChanged, this.onSelectionChanged,
this.onCaretChanged, this.onCaretChanged,
...@@ -1944,6 +1953,7 @@ class _Editable extends LeafRenderObjectWidget { ...@@ -1944,6 +1953,7 @@ class _Editable extends LeafRenderObjectWidget {
final bool obscureText; final bool obscureText;
final TextWidthBasis textWidthBasis; final TextWidthBasis textWidthBasis;
final bool autocorrect; final bool autocorrect;
final bool enableSuggestions;
final ViewportOffset offset; final ViewportOffset offset;
final SelectionChangedHandler onSelectionChanged; final SelectionChangedHandler onSelectionChanged;
final CaretChangedHandler onCaretChanged; final CaretChangedHandler onCaretChanged;
......
...@@ -119,6 +119,7 @@ void main() { ...@@ -119,6 +119,7 @@ void main() {
expect(editableText.maxLines, equals(1)); expect(editableText.maxLines, equals(1));
expect(editableText.obscureText, isFalse); expect(editableText.obscureText, isFalse);
expect(editableText.autocorrect, isTrue); expect(editableText.autocorrect, isTrue);
expect(editableText.enableSuggestions, isTrue);
expect(editableText.textAlign, TextAlign.start); expect(editableText.textAlign, TextAlign.start);
expect(editableText.cursorWidth, 2.0); expect(editableText.cursorWidth, 2.0);
}); });
...@@ -327,6 +328,36 @@ void main() { ...@@ -327,6 +328,36 @@ void main() {
equals('TextInputAction.done')); equals('TextInputAction.done'));
}); });
testWidgets('enableSuggestions flag is sent to the engine properly', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController();
const bool enableSuggestions = false;
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(devicePixelRatio: 1.0),
child: Directionality(
textDirection: TextDirection.ltr,
child: FocusScope(
node: focusScopeNode,
autofocus: true,
child: EditableText(
controller: controller,
backgroundCursorColor: Colors.grey,
focusNode: focusNode,
enableSuggestions: enableSuggestions,
style: textStyle,
cursorColor: cursorColor,
),
),
),
),
);
await tester.tap(find.byType(EditableText));
await tester.showKeyboard(find.byType(EditableText));
await tester.idle();
expect(tester.testTextInput.setClientArgs['enableSuggestions'], enableSuggestions);
});
testWidgets('selection overlay will update when text grow bigger', (WidgetTester tester) async { testWidgets('selection overlay will update when text grow bigger', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController.fromValue( final TextEditingController controller = TextEditingController.fromValue(
const TextEditingValue( const TextEditingValue(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment