Unverified Commit a3b7feb8 authored by chunhtai's avatar chunhtai Committed by GitHub

Editable text sends enableInteractiveSelection to text input client (#100649)

* Editable text sends enableInteractiveSelection to text input client

* addressing comments
parent b346a593
...@@ -461,6 +461,7 @@ class TextInputConfiguration { ...@@ -461,6 +461,7 @@ class TextInputConfiguration {
SmartDashesType? smartDashesType, SmartDashesType? smartDashesType,
SmartQuotesType? smartQuotesType, SmartQuotesType? smartQuotesType,
this.enableSuggestions = true, this.enableSuggestions = true,
this.enableInteractiveSelection = true,
this.actionLabel, this.actionLabel,
this.inputAction = TextInputAction.done, this.inputAction = TextInputAction.done,
this.keyboardAppearance = Brightness.light, this.keyboardAppearance = Brightness.light,
...@@ -571,6 +572,15 @@ class TextInputConfiguration { ...@@ -571,6 +572,15 @@ class TextInputConfiguration {
/// {@endtemplate} /// {@endtemplate}
final bool enableSuggestions; final bool enableSuggestions;
/// Whether a user can change its selection.
///
/// This flag only affects iOS VoiceOver. On Android Talkback, the selection
/// change is sent through semantics actions and is directly disabled from
/// the widget side.
///
/// Defaults to true. Cannot be null.
final bool enableInteractiveSelection;
/// 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;
...@@ -618,6 +628,7 @@ class TextInputConfiguration { ...@@ -618,6 +628,7 @@ class TextInputConfiguration {
SmartDashesType? smartDashesType, SmartDashesType? smartDashesType,
SmartQuotesType? smartQuotesType, SmartQuotesType? smartQuotesType,
bool? enableSuggestions, bool? enableSuggestions,
bool? enableInteractiveSelection,
String? actionLabel, String? actionLabel,
TextInputAction? inputAction, TextInputAction? inputAction,
Brightness? keyboardAppearance, Brightness? keyboardAppearance,
...@@ -634,6 +645,7 @@ class TextInputConfiguration { ...@@ -634,6 +645,7 @@ class TextInputConfiguration {
smartDashesType: smartDashesType ?? this.smartDashesType, smartDashesType: smartDashesType ?? this.smartDashesType,
smartQuotesType: smartQuotesType ?? this.smartQuotesType, smartQuotesType: smartQuotesType ?? this.smartQuotesType,
enableSuggestions: enableSuggestions ?? this.enableSuggestions, enableSuggestions: enableSuggestions ?? this.enableSuggestions,
enableInteractiveSelection: enableInteractiveSelection ?? this.enableInteractiveSelection,
inputAction: inputAction ?? this.inputAction, inputAction: inputAction ?? this.inputAction,
textCapitalization: textCapitalization ?? this.textCapitalization, textCapitalization: textCapitalization ?? this.textCapitalization,
keyboardAppearance: keyboardAppearance ?? this.keyboardAppearance, keyboardAppearance: keyboardAppearance ?? this.keyboardAppearance,
...@@ -679,6 +691,7 @@ class TextInputConfiguration { ...@@ -679,6 +691,7 @@ class TextInputConfiguration {
'smartDashesType': smartDashesType.index.toString(), 'smartDashesType': smartDashesType.index.toString(),
'smartQuotesType': smartQuotesType.index.toString(), 'smartQuotesType': smartQuotesType.index.toString(),
'enableSuggestions': enableSuggestions, 'enableSuggestions': enableSuggestions,
'enableInteractiveSelection': enableInteractiveSelection,
'actionLabel': actionLabel, 'actionLabel': actionLabel,
'inputAction': inputAction.toString(), 'inputAction': inputAction.toString(),
'textCapitalization': textCapitalization.toString(), 'textCapitalization': textCapitalization.toString(),
......
...@@ -1387,6 +1387,8 @@ class EditableText extends StatefulWidget { ...@@ -1387,6 +1387,8 @@ class EditableText extends StatefulWidget {
/// {@macro flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning} /// {@macro flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning}
final bool enableIMEPersonalizedLearning; final bool enableIMEPersonalizedLearning;
bool get _userSelectionEnabled => enableInteractiveSelection && (!readOnly || !obscureText);
// Infer the keyboard type of an `EditableText` if it's not specified. // Infer the keyboard type of an `EditableText` if it's not specified.
static TextInputType _inferKeyboardType({ static TextInputType _inferKeyboardType({
required Iterable<String>? autofillHints, required Iterable<String>? autofillHints,
...@@ -3021,6 +3023,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -3021,6 +3023,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
smartDashesType: widget.smartDashesType, smartDashesType: widget.smartDashesType,
smartQuotesType: widget.smartQuotesType, smartQuotesType: widget.smartQuotesType,
enableSuggestions: widget.enableSuggestions, enableSuggestions: widget.enableSuggestions,
enableInteractiveSelection: widget._userSelectionEnabled,
inputAction: widget.textInputAction ?? (widget.keyboardType == TextInputType.multiline inputAction: widget.textInputAction ?? (widget.keyboardType == TextInputType.multiline
? TextInputAction.newline ? TextInputAction.newline
: TextInputAction.done : TextInputAction.done
...@@ -3327,7 +3330,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -3327,7 +3330,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
selectionHeightStyle: widget.selectionHeightStyle, selectionHeightStyle: widget.selectionHeightStyle,
selectionWidthStyle: widget.selectionWidthStyle, selectionWidthStyle: widget.selectionWidthStyle,
paintCursorAboveText: widget.paintCursorAboveText, paintCursorAboveText: widget.paintCursorAboveText,
enableInteractiveSelection: widget.enableInteractiveSelection && (!widget.readOnly || !widget.obscureText), enableInteractiveSelection: widget._userSelectionEnabled,
textSelectionDelegate: this, textSelectionDelegate: this,
devicePixelRatio: _devicePixelRatio, devicePixelRatio: _devicePixelRatio,
promptRectRange: _currentPromptRectRange, promptRectRange: _currentPromptRectRange,
......
...@@ -569,6 +569,58 @@ void main() { ...@@ -569,6 +569,58 @@ void main() {
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.newline')); expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.newline'));
}); });
testWidgets('EditableText sends enableInteractiveSelection to config', (WidgetTester tester) async {
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(),
child: Directionality(
textDirection: TextDirection.ltr,
child: FocusScope(
node: focusScopeNode,
autofocus: true,
child: EditableText(
enableInteractiveSelection: true,
controller: controller,
backgroundCursorColor: Colors.grey,
focusNode: focusNode,
keyboardType: TextInputType.multiline,
style: textStyle,
cursorColor: cursorColor,
),
),
),
),
);
EditableTextState state = tester.state<EditableTextState>(find.byType(EditableText));
expect(state.textInputConfiguration.enableInteractiveSelection, isTrue);
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(),
child: Directionality(
textDirection: TextDirection.ltr,
child: FocusScope(
node: focusScopeNode,
autofocus: true,
child: EditableText(
enableInteractiveSelection: false,
controller: controller,
backgroundCursorColor: Colors.grey,
focusNode: focusNode,
keyboardType: TextInputType.multiline,
style: textStyle,
cursorColor: cursorColor,
),
),
),
),
);
state = tester.state<EditableTextState>(find.byType(EditableText));
expect(state.textInputConfiguration.enableInteractiveSelection, isFalse);
});
testWidgets('selection persists when unfocused', (WidgetTester tester) async { testWidgets('selection persists when unfocused', (WidgetTester tester) async {
const TextEditingValue value = TextEditingValue( const TextEditingValue value = TextEditingValue(
text: 'test test', text: 'test test',
......
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