Commit 6bdd2883 authored by Jason Simmons's avatar Jason Simmons

Merge pull request #1615 from jason-simmons/edit_text_action_button_2

Implement better synchronization between the state of the input widget and the keyboard IME
parents 3c94991c 98b83e0c
...@@ -13,6 +13,7 @@ import 'theme.dart'; ...@@ -13,6 +13,7 @@ import 'theme.dart';
export 'package:flutter/services.dart' show KeyboardType; export 'package:flutter/services.dart' show KeyboardType;
typedef void StringValueChanged(String value); typedef void StringValueChanged(String value);
typedef void StringValueSubmitted(String value);
// TODO(eseidel): This isn't right, it's 16px on the bottom: // TODO(eseidel): This isn't right, it's 16px on the bottom:
// http://www.google.com/design/spec/components/text-fields.html#text-fields-single-line-text-field // http://www.google.com/design/spec/components/text-fields.html#text-fields-single-line-text-field
...@@ -24,7 +25,8 @@ class Input extends Scrollable { ...@@ -24,7 +25,8 @@ class Input extends Scrollable {
this.initialValue: '', this.initialValue: '',
this.placeholder, this.placeholder,
this.onChanged, this.onChanged,
this.keyboardType: KeyboardType.TEXT this.keyboardType: KeyboardType.TEXT,
this.onSubmitted
}) : super( }) : super(
key: key, key: key,
initialScrollOffset: 0.0, initialScrollOffset: 0.0,
...@@ -35,6 +37,7 @@ class Input extends Scrollable { ...@@ -35,6 +37,7 @@ class Input extends Scrollable {
final KeyboardType keyboardType; final KeyboardType keyboardType;
final String placeholder; final String placeholder;
final StringValueChanged onChanged; final StringValueChanged onChanged;
final StringValueSubmitted onSubmitted;
_InputState createState() => new _InputState(); _InputState createState() => new _InputState();
} }
...@@ -52,7 +55,8 @@ class _InputState extends ScrollableState<Input> { ...@@ -52,7 +55,8 @@ class _InputState extends ScrollableState<Input> {
_value = config.initialValue; _value = config.initialValue;
_editableValue = new EditableString( _editableValue = new EditableString(
text: _value, text: _value,
onUpdated: _handleTextUpdated onUpdated: _handleTextUpdated,
onSubmitted: _handleTextSubmitted
); );
} }
...@@ -66,12 +70,20 @@ class _InputState extends ScrollableState<Input> { ...@@ -66,12 +70,20 @@ class _InputState extends ScrollableState<Input> {
} }
} }
void _handleTextSubmitted() {
if (config.onSubmitted != null)
config.onSubmitted(_value);
}
Widget buildContent(BuildContext context) { Widget buildContent(BuildContext context) {
ThemeData themeData = Theme.of(context); ThemeData themeData = Theme.of(context);
bool focused = Focus.at(context, config); bool focused = Focus.at(context, config);
if (focused && !_keyboardHandle.attached) { if (focused && !_keyboardHandle.attached) {
_keyboardHandle = keyboard.show(_editableValue.stub, config.keyboardType); _keyboardHandle = keyboard.show(_editableValue.stub, config.keyboardType);
_keyboardHandle.setText(_editableValue.text);
_keyboardHandle.setSelection(_editableValue.selection.start,
_editableValue.selection.end);
} else if (!focused && _keyboardHandle.attached) { } else if (!focused && _keyboardHandle.attached) {
_keyboardHandle.release(); _keyboardHandle.release();
} }
......
...@@ -77,6 +77,18 @@ class KeyboardHandle { ...@@ -77,6 +77,18 @@ class KeyboardHandle {
assert(_keyboard._currentHandle != this); assert(_keyboard._currentHandle != this);
} }
void setText(String text) {
assert(_attached);
assert(_keyboard._currentHandle == this);
_keyboard.service.setText(text);
}
void setSelection(int start, int end) {
assert(_attached);
assert(_keyboard._currentHandle == this);
_keyboard.service.setSelection(start, end);
}
} }
final Keyboard keyboard = new Keyboard(_KeyboardConnection.instance.keyboardService); final Keyboard keyboard = new Keyboard(_KeyboardConnection.instance.keyboardService);
...@@ -14,6 +14,7 @@ import 'framework.dart'; ...@@ -14,6 +14,7 @@ import 'framework.dart';
const _kCursorBlinkHalfPeriod = 500; // milliseconds const _kCursorBlinkHalfPeriod = 500; // milliseconds
typedef void StringUpdated(); typedef void StringUpdated();
typedef void StringSubmitted();
class TextRange { class TextRange {
const TextRange({ this.start, this.end }); const TextRange({ this.start, this.end });
...@@ -32,18 +33,22 @@ class TextRange { ...@@ -32,18 +33,22 @@ class TextRange {
} }
class EditableString implements KeyboardClient { class EditableString implements KeyboardClient {
EditableString({this.text: '', this.onUpdated, this.onSubmitted}) {
assert(onUpdated != null);
assert(onSubmitted != null);
stub = new KeyboardClientStub.unbound()..impl = this;
selection = new TextRange(start: text.length, end: text.length);
}
String text; String text;
TextRange composing = const TextRange.empty(); TextRange composing = const TextRange.empty();
TextRange selection = const TextRange.empty(); TextRange selection;
final StringUpdated onUpdated; final StringUpdated onUpdated;
final StringSubmitted onSubmitted;
KeyboardClientStub stub; KeyboardClientStub stub;
EditableString({this.text: '', this.onUpdated}) {
stub = new KeyboardClientStub.unbound()..impl = this;
}
String textBefore(TextRange range) { String textBefore(TextRange range) {
return text.substring(0, range.start); return text.substring(0, range.start);
} }
...@@ -129,7 +134,9 @@ class EditableString implements KeyboardClient { ...@@ -129,7 +134,9 @@ class EditableString implements KeyboardClient {
onUpdated(); onUpdated();
} }
void submit(SubmitAction action) {} void submit(SubmitAction action) {
onSubmitted();
}
} }
class EditableText extends StatefulComponent { class EditableText extends StatefulComponent {
......
...@@ -17,6 +17,10 @@ class MockKeyboard implements KeyboardService { ...@@ -17,6 +17,10 @@ class MockKeyboard implements KeyboardService {
void showByRequest() {} void showByRequest() {}
void hide() {} void hide() {}
void setText(String text) {}
void setSelection(int start, int end) {}
} }
void main() { void main() {
......
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