Commit 98b83e0c authored by Jason Simmons's avatar Jason Simmons

Implement better synchronization between the state of the input widget and the keyboard IME

Also add an input widget API for the keyboard submit button
parent 1beda0d6
......@@ -13,6 +13,7 @@ import 'theme.dart';
export 'package:flutter/services.dart' show KeyboardType;
typedef void StringValueChanged(String value);
typedef void StringValueSubmitted(String value);
// 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
......@@ -24,7 +25,8 @@ class Input extends Scrollable {
this.initialValue: '',
this.placeholder,
this.onChanged,
this.keyboardType: KeyboardType.TEXT
this.keyboardType: KeyboardType.TEXT,
this.onSubmitted
}) : super(
key: key,
initialScrollOffset: 0.0,
......@@ -35,6 +37,7 @@ class Input extends Scrollable {
final KeyboardType keyboardType;
final String placeholder;
final StringValueChanged onChanged;
final StringValueSubmitted onSubmitted;
_InputState createState() => new _InputState();
}
......@@ -52,7 +55,8 @@ class _InputState extends ScrollableState<Input> {
_value = config.initialValue;
_editableValue = new EditableString(
text: _value,
onUpdated: _handleTextUpdated
onUpdated: _handleTextUpdated,
onSubmitted: _handleTextSubmitted
);
}
......@@ -66,12 +70,20 @@ class _InputState extends ScrollableState<Input> {
}
}
void _handleTextSubmitted() {
if (config.onSubmitted != null)
config.onSubmitted(_value);
}
Widget buildContent(BuildContext context) {
ThemeData themeData = Theme.of(context);
bool focused = Focus.at(context, config);
if (focused && !_keyboardHandle.attached) {
_keyboardHandle = keyboard.show(_editableValue.stub, config.keyboardType);
_keyboardHandle.setText(_editableValue.text);
_keyboardHandle.setSelection(_editableValue.selection.start,
_editableValue.selection.end);
} else if (!focused && _keyboardHandle.attached) {
_keyboardHandle.release();
}
......
......@@ -77,6 +77,18 @@ class KeyboardHandle {
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);
......@@ -14,6 +14,7 @@ import 'framework.dart';
const _kCursorBlinkHalfPeriod = 500; // milliseconds
typedef void StringUpdated();
typedef void StringSubmitted();
class TextRange {
const TextRange({ this.start, this.end });
......@@ -32,18 +33,22 @@ class TextRange {
}
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;
TextRange composing = const TextRange.empty();
TextRange selection = const TextRange.empty();
TextRange selection;
final StringUpdated onUpdated;
final StringSubmitted onSubmitted;
KeyboardClientStub stub;
EditableString({this.text: '', this.onUpdated}) {
stub = new KeyboardClientStub.unbound()..impl = this;
}
String textBefore(TextRange range) {
return text.substring(0, range.start);
}
......@@ -129,7 +134,9 @@ class EditableString implements KeyboardClient {
onUpdated();
}
void submit(SubmitAction action) {}
void submit(SubmitAction action) {
onSubmitted();
}
}
class EditableText extends StatefulComponent {
......
......@@ -17,6 +17,10 @@ class MockKeyboard implements KeyboardService {
void showByRequest() {}
void hide() {}
void setText(String text) {}
void setSelection(int start, int end) {}
}
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