Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/flutter/lib/src/cupertino/text_form_field_row.dart
Original file line number Diff line number Diff line change
Expand Up @@ -360,15 +360,15 @@ class _CupertinoTextFormFieldRowState extends FormFieldState<String> {
super.didChange(value);

if (value != null && _effectiveController.text != value) {
_effectiveController.text = value;
_effectiveController.value = TextEditingValue(text: value);
}
}

@override
void reset() {
// Set the controller value before calling super.reset() to let
// _handleControllerChanged suppress the change.
_effectiveController.text = widget.initialValue!;
_effectiveController.value = TextEditingValue(text: widget.initialValue ?? '');
super.reset();
_cupertinoTextFormFieldRow.onChanged?.call(_effectiveController.text);
}
Expand Down
10 changes: 4 additions & 6 deletions packages/flutter/lib/src/material/search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,10 @@ abstract class SearchDelegate<T> {
///
/// Setting the query string programmatically moves the cursor to the end of the text field.
set query(String value) {
_queryTextController.text = value;
if (_queryTextController.text.isNotEmpty) {
_queryTextController.selection = TextSelection.fromPosition(
TextPosition(offset: _queryTextController.text.length),
);
}
_queryTextController.value = TextEditingValue(
text: value,
selection: TextSelection.collapsed(offset: value.length),
);
}

/// Transition from the suggestions returned by [buildSuggestions] to the
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/material/search_anchor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ class _SearchAnchorState extends State<SearchAnchor> {

void _closeView(String? selectedText) {
if (selectedText != null) {
_searchController.text = selectedText;
_searchController.value = TextEditingValue(text: selectedText);
}
Navigator.of(context).pop();
}
Expand Down
4 changes: 2 additions & 2 deletions packages/flutter/lib/src/material/text_form_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -403,15 +403,15 @@ class _TextFormFieldState extends FormFieldState<String> {
super.didChange(value);

if (_effectiveController.text != value) {
_effectiveController.text = value ?? '';
_effectiveController.value = TextEditingValue(text: value ?? '');
}
}

@override
void reset() {
// Set the controller value before calling super.reset() to let
// _handleControllerChanged suppress the change.
_effectiveController.text = widget.initialValue ?? '';
_effectiveController.value = TextEditingValue(text: widget.initialValue ?? '');
super.reset();
_textFormField.onChanged?.call(_effectiveController.text);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/material/time_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2098,7 +2098,7 @@ class _HourMinuteTextFieldState extends State<_HourMinuteTextField> with Restora
// version yet.
if (!controllerHasBeenSet.value) {
controllerHasBeenSet.value = true;
controller.value.text = _formattedValue;
controller.value.value = TextEditingValue(text: _formattedValue);
}
}

Expand Down
20 changes: 11 additions & 9 deletions packages/flutter/lib/src/widgets/editable_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -258,17 +258,19 @@ class TextEditingController extends ValueNotifier<TextEditingValue> {
/// The current string the user is editing.
String get text => value.text;

/// Setting this will notify all the listeners of this [TextEditingController]
/// Updates the current [text] to the given `newText`, and removes existing
/// selection and composing range held by the controller.
///
/// This setter is typically only used in tests, as it resets the cursor
/// position and the composing state. For production code, **consider using the
/// [value] setter to update the [text] value instead**, and specify a
/// reasonable selection range within the new [text].
///
/// Setting this notifies all the listeners of this [TextEditingController]
/// that they need to update (it calls [notifyListeners]). For this reason,
/// this value should only be set between frames, e.g. in response to user
/// actions, not during the build, layout, or paint phases.
///
/// This property can be set from a listener added to this
/// [TextEditingController]; **however, one should not also set [selection]
/// in a separate statement. To change both the [text] and the [selection]
/// change the controller's [value].** Setting this here will clear
/// the current selection and composing range, so avoid using it directly
/// unless that is the desired behavior.
/// actions, not during the build, layout, or paint phases. This property can
/// be set from a listener added to this [TextEditingController].
set text(String newText) {
value = value.copyWith(
text: newText,
Expand Down
3 changes: 3 additions & 0 deletions packages/flutter/test/material/search_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ void main() {
textField.controller!.selection,
TextSelection(baseOffset: delegate.query.length, extentOffset: delegate.query.length),
);

delegate.query = '';
expect(textField.controller!.selection, const TextSelection.collapsed(offset: 0));
});

testWidgets('Can open and close search', (WidgetTester tester) async {
Expand Down
Loading