Commit 470db7d9 authored by Adam Barth's avatar Adam Barth Committed by GitHub

TextField should update IME when controller changes (#9261)

Fixes #9246
parent 249bbac3
...@@ -239,9 +239,8 @@ class EditableTextState extends State<EditableText> implements TextInputClient { ...@@ -239,9 +239,8 @@ class EditableTextState extends State<EditableText> implements TextInputClient {
if (config.controller != oldConfig.controller) { if (config.controller != oldConfig.controller) {
oldConfig.controller.removeListener(_didChangeTextEditingValue); oldConfig.controller.removeListener(_didChangeTextEditingValue);
config.controller.addListener(_didChangeTextEditingValue); config.controller.addListener(_didChangeTextEditingValue);
if (_hasInputConnection && config.controller.value != oldConfig.controller.value) _updateRemoteEditingValueIfNeeded();
_textInputConnection.setEditingState(config.controller.value); }
}
if (config.focusNode != oldConfig.focusNode) { if (config.focusNode != oldConfig.focusNode) {
oldConfig.focusNode.removeListener(_handleFocusChanged); oldConfig.focusNode.removeListener(_handleFocusChanged);
config.focusNode.addListener(_handleFocusChanged); config.focusNode.addListener(_handleFocusChanged);
...@@ -263,10 +262,13 @@ class EditableTextState extends State<EditableText> implements TextInputClient { ...@@ -263,10 +262,13 @@ class EditableTextState extends State<EditableText> implements TextInputClient {
// TextInputClient implementation: // TextInputClient implementation:
TextEditingValue _lastKnownRemoteTextEditingValue;
@override @override
void updateEditingValue(TextEditingValue value) { void updateEditingValue(TextEditingValue value) {
if (value.text != _value.text) if (value.text != _value.text)
_hideSelectionOverlayIfNeeded(); _hideSelectionOverlayIfNeeded();
_lastKnownRemoteTextEditingValue = value;
_value = value; _value = value;
if (config.onChanged != null) if (config.onChanged != null)
config.onChanged(value.text); config.onChanged(value.text);
...@@ -280,6 +282,16 @@ class EditableTextState extends State<EditableText> implements TextInputClient { ...@@ -280,6 +282,16 @@ class EditableTextState extends State<EditableText> implements TextInputClient {
config.onSubmitted(_value.text); config.onSubmitted(_value.text);
} }
void _updateRemoteEditingValueIfNeeded() {
if (!_hasInputConnection)
return;
final TextEditingValue localValue = _value;
if (localValue == _lastKnownRemoteTextEditingValue)
return;
_lastKnownRemoteTextEditingValue = localValue;
_textInputConnection.setEditingState(localValue);
}
TextEditingValue get _value => config.controller.value; TextEditingValue get _value => config.controller.value;
set _value(TextEditingValue value) { set _value(TextEditingValue value) {
config.controller.value = value; config.controller.value = value;
...@@ -306,8 +318,10 @@ class EditableTextState extends State<EditableText> implements TextInputClient { ...@@ -306,8 +318,10 @@ class EditableTextState extends State<EditableText> implements TextInputClient {
void _openInputConnectionIfNeeded() { void _openInputConnectionIfNeeded() {
if (!_hasInputConnection) { if (!_hasInputConnection) {
final TextEditingValue localValue = _value;
_lastKnownRemoteTextEditingValue = localValue;
_textInputConnection = TextInput.attach(this, new TextInputConfiguration(inputType: config.keyboardType)) _textInputConnection = TextInput.attach(this, new TextInputConfiguration(inputType: config.keyboardType))
..setEditingState(_value) ..setEditingState(localValue)
..show(); ..show();
} }
} }
...@@ -316,6 +330,7 @@ class EditableTextState extends State<EditableText> implements TextInputClient { ...@@ -316,6 +330,7 @@ class EditableTextState extends State<EditableText> implements TextInputClient {
if (_hasInputConnection) { if (_hasInputConnection) {
_textInputConnection.close(); _textInputConnection.close();
_textInputConnection = null; _textInputConnection = null;
_lastKnownRemoteTextEditingValue = null;
} }
} }
...@@ -429,6 +444,7 @@ class EditableTextState extends State<EditableText> implements TextInputClient { ...@@ -429,6 +444,7 @@ class EditableTextState extends State<EditableText> implements TextInputClient {
} }
void _didChangeTextEditingValue() { void _didChangeTextEditingValue() {
_updateRemoteEditingValueIfNeeded();
_startOrStopCursorTimerIfNeeded(); _startOrStopCursorTimerIfNeeded();
_updateOrDisposeSelectionOverlayIfNeeded(); _updateOrDisposeSelectionOverlayIfNeeded();
// TODO(abarth): Teach RenderEditable about ValueNotifier<TextEditingValue> // TODO(abarth): Teach RenderEditable about ValueNotifier<TextEditingValue>
......
...@@ -886,4 +886,59 @@ void main() { ...@@ -886,4 +886,59 @@ void main() {
expect(topLeft.x, equals(399.0)); expect(topLeft.x, equals(399.0));
}); });
testWidgets('Controller can update server', (WidgetTester tester) async {
final TextEditingController controller = new TextEditingController(
text: 'Initial Text',
);
final TextEditingController controller2 = new TextEditingController(
text: 'More Text',
);
TextEditingController currentController = controller;
StateSetter setState;
await tester.pumpWidget(
overlay(new Center(
child: new Material(
child: new StatefulBuilder(
builder: (BuildContext context, StateSetter setter) {
setState = setter;
return new TextField(controller: currentController);
}
),
),
),
));
expect(tester.testTextInput.editingState['text'], isEmpty);
await tester.tap(find.byType(TextField));
await tester.pump();
expect(tester.testTextInput.editingState['text'], equals('Initial Text'));
controller.text = 'Updated Text';
await tester.idle();
expect(tester.testTextInput.editingState['text'], equals('Updated Text'));
setState(() {
currentController = controller2;
});
await tester.pump();
expect(tester.testTextInput.editingState['text'], equals('More Text'));
controller.text = 'Ignored Text';
await tester.idle();
expect(tester.testTextInput.editingState['text'], equals('More Text'));
controller2.text = 'Final Text';
await tester.idle();
expect(tester.testTextInput.editingState['text'], equals('Final Text'));
});
} }
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