mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Support correct keyboards for multi-line text editing. (#4115)
This addresses part of #8028, implementing the Engine-side support for it.
This commit is contained in:
parent
9c518cb751
commit
faabc10178
@ -8,6 +8,7 @@ import android.content.Context;
|
||||
import android.text.Editable;
|
||||
import android.text.Selection;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
@ -92,7 +93,7 @@ class InputConnectionAdaptor extends BaseInputConnection {
|
||||
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
||||
if (Selection.getSelectionStart(mEditable) == -1 ||
|
||||
Selection.getSelectionStart(mEditable) == -1)
|
||||
return true;
|
||||
return true;9c518cb751e34b0
|
||||
|
||||
boolean result = super.deleteSurroundingText(beforeLength, afterLength);
|
||||
updateEditingState();
|
||||
@ -162,8 +163,17 @@ class InputConnectionAdaptor extends BaseInputConnection {
|
||||
@Override
|
||||
public boolean performEditorAction(int actionCode) {
|
||||
// TODO(abarth): Support more actions.
|
||||
mFlutterChannel.invokeMethod("TextInputClient.performAction",
|
||||
Arrays.asList(mClient, "TextInputAction.done"));
|
||||
switch (actionCode) {
|
||||
case EditorInfo.IME_ACTION_NONE:
|
||||
mFlutterChannel.invokeMethod("TextInputClient.performAction",
|
||||
Arrays.asList(mClient, "TextInputAction.newline"));
|
||||
break;
|
||||
default:
|
||||
case EditorInfo.IME_ACTION_DONE:
|
||||
mFlutterChannel.invokeMethod("TextInputClient.performAction",
|
||||
Arrays.asList(mClient, "TextInputAction.done"));
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +88,9 @@ public class TextInputPlugin implements MethodCallHandler {
|
||||
return InputType.TYPE_CLASS_PHONE;
|
||||
|
||||
int textType = InputType.TYPE_CLASS_TEXT;
|
||||
if (inputType.equals("TextInputType.emailAddress"))
|
||||
if (inputType.equals("TextInputType.multiline"))
|
||||
textType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE;
|
||||
else if (inputType.equals("TextInputType.emailAddress"))
|
||||
textType |= InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
|
||||
else if (inputType.equals("TextInputType.url"))
|
||||
textType |= InputType.TYPE_TEXT_VARIATION_URI;
|
||||
@ -102,6 +104,12 @@ public class TextInputPlugin implements MethodCallHandler {
|
||||
return textType;
|
||||
}
|
||||
|
||||
private static int inputActionFromTextInputAction(String inputAction) {
|
||||
if (inputAction.equals("TextInputAction.newline"))
|
||||
return EditorInfo.IME_ACTION_NONE;
|
||||
return EditorInfo.IME_ACTION_DONE;
|
||||
}
|
||||
|
||||
public InputConnection createInputConnection(FlutterView view, EditorInfo outAttrs)
|
||||
throws JSONException {
|
||||
if (mClient == 0)
|
||||
@ -111,9 +119,22 @@ public class TextInputPlugin implements MethodCallHandler {
|
||||
mConfiguration.getString("inputType"),
|
||||
mConfiguration.optBoolean("obscureText"),
|
||||
mConfiguration.optBoolean("autocorrect", true));
|
||||
if (!mConfiguration.isNull("actionLabel"))
|
||||
outAttrs.actionLabel = mConfiguration.getString("actionLabel");
|
||||
outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_FULLSCREEN;
|
||||
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
|
||||
int enterAction;
|
||||
if (mConfiguration.isNull("inputAction")) {
|
||||
// If an explicit input action isn't set, then default to none for multi-line fields
|
||||
// and done for single line fields.
|
||||
enterAction = (InputType.TYPE_TEXT_FLAG_MULTI_LINE & outAttrs.inputType) != 0
|
||||
? EditorInfo.IME_ACTION_NONE
|
||||
: EditorInfo.IME_ACTION_DONE;
|
||||
} else {
|
||||
enterAction = inputActionFromTextInputAction(mConfiguration.getString("inputAction"));
|
||||
}
|
||||
if (!mConfiguration.isNull("actionLabel")) {
|
||||
outAttrs.actionLabel = mConfiguration.getString("actionLabel");
|
||||
outAttrs.actionId = enterAction;
|
||||
}
|
||||
outAttrs.imeOptions |= enterAction;
|
||||
|
||||
InputConnectionAdaptor connection = new InputConnectionAdaptor(view, mClient, mFlutterChannel, mEditable);
|
||||
outAttrs.initialSelStart = Math.max(Selection.getSelectionStart(mEditable), 0);
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
typedef NS_ENUM(NSInteger, FlutterTextInputAction) {
|
||||
FlutterTextInputActionDone,
|
||||
FlutterTextInputActionNewline,
|
||||
};
|
||||
|
||||
@protocol FlutterTextInputDelegate<NSObject>
|
||||
|
||||
@ -12,6 +12,8 @@ static const char _kTextAffinityUpstream[] = "TextAffinity.upstream";
|
||||
static UIKeyboardType ToUIKeyboardType(NSString* inputType) {
|
||||
if ([inputType isEqualToString:@"TextInputType.text"])
|
||||
return UIKeyboardTypeDefault;
|
||||
if ([inputType isEqualToString:@"TextInputType.multiline"])
|
||||
return UIKeyboardTypeDefault;
|
||||
if ([inputType isEqualToString:@"TextInputType.number"])
|
||||
return UIKeyboardTypeDecimalPad;
|
||||
if ([inputType isEqualToString:@"TextInputType.phone"])
|
||||
@ -23,6 +25,12 @@ static UIKeyboardType ToUIKeyboardType(NSString* inputType) {
|
||||
return UIKeyboardTypeDefault;
|
||||
}
|
||||
|
||||
static UIReturnKeyType ToUIReturnKeyType(NSString* inputType) {
|
||||
if ([inputType isEqualToString:@"TextInputType.multiline"])
|
||||
return UIReturnKeyDefault;
|
||||
return UIReturnKeyDone;
|
||||
}
|
||||
|
||||
static UITextAutocapitalizationType ToUITextAutocapitalizationType(NSString* inputType) {
|
||||
if ([inputType isEqualToString:@"TextInputType.text"])
|
||||
return UITextAutocapitalizationTypeSentences;
|
||||
@ -272,6 +280,8 @@ static UITextAutocapitalizationType ToUITextAutocapitalizationType(NSString* inp
|
||||
[_textInputDelegate performAction:FlutterTextInputActionDone withClient:_textInputClient];
|
||||
return NO;
|
||||
}
|
||||
if (self.returnKeyType == UIReturnKeyDefault && [text isEqualToString:@"\n"])
|
||||
[_textInputDelegate performAction:FlutterTextInputActionNewline withClient:_textInputClient];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -569,6 +579,7 @@ static UITextAutocapitalizationType ToUITextAutocapitalizationType(NSString* inp
|
||||
|
||||
- (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configuration {
|
||||
_view.keyboardType = ToUIKeyboardType(configuration[@"inputType"]);
|
||||
_view.returnKeyType = ToUIReturnKeyType(configuration[@"inputType"]);
|
||||
_view.autocapitalizationType = ToUITextAutocapitalizationType(configuration[@"inputType"]);
|
||||
_view.secureTextEntry = [configuration[@"obscureText"] boolValue];
|
||||
NSString* autocorrect = configuration[@"autocorrect"];
|
||||
|
||||
@ -626,6 +626,9 @@ static inline blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* to
|
||||
case FlutterTextInputActionDone:
|
||||
actionString = @"TextInputAction.done";
|
||||
break;
|
||||
case FlutterTextInputActionNewline:
|
||||
actionString = @"TextInputAction.newline";
|
||||
break;
|
||||
}
|
||||
[_textInputChannel.get() invokeMethod:@"TextInputClient.performAction"
|
||||
arguments:@[ @(client), actionString ]];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user