Support all keyboard actions. (#11344) (#5620)

* Support all keyboard actions. (#11344)
This commit is contained in:
matthew-carroll 2018-07-02 06:58:01 +00:00 committed by GitHub
parent bc6b2501c2
commit 061e899b55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 173 additions and 13 deletions

View File

@ -172,12 +172,36 @@ class InputConnectionAdaptor extends BaseInputConnection {
@Override
public boolean performEditorAction(int actionCode) {
// TODO(abarth): Support more actions.
switch (actionCode) {
// TODO(mattcarroll): is newline an appropriate action for "none"?
case EditorInfo.IME_ACTION_NONE:
mFlutterChannel.invokeMethod("TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.newline"));
break;
case EditorInfo.IME_ACTION_UNSPECIFIED:
mFlutterChannel.invokeMethod("TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.unspecified"));
break;
case EditorInfo.IME_ACTION_GO:
mFlutterChannel.invokeMethod("TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.go"));
break;
case EditorInfo.IME_ACTION_SEARCH:
mFlutterChannel.invokeMethod("TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.search"));
break;
case EditorInfo.IME_ACTION_SEND:
mFlutterChannel.invokeMethod("TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.send"));
break;
case EditorInfo.IME_ACTION_NEXT:
mFlutterChannel.invokeMethod("TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.next"));
break;
case EditorInfo.IME_ACTION_PREVIOUS:
mFlutterChannel.invokeMethod("TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.previous"));
break;
default:
case EditorInfo.IME_ACTION_DONE:
mFlutterChannel.invokeMethod("TextInputClient.performAction",

View File

@ -115,9 +115,29 @@ public class TextInputPlugin implements MethodCallHandler {
}
private static int inputActionFromTextInputAction(String inputAction) {
if (inputAction.equals("TextInputAction.newline"))
return EditorInfo.IME_ACTION_NONE;
return EditorInfo.IME_ACTION_DONE;
switch (inputAction) {
case "TextInputAction.newline":
return EditorInfo.IME_ACTION_NONE;
case "TextInputAction.none":
return EditorInfo.IME_ACTION_NONE;
case "TextInputAction.unspecified":
return EditorInfo.IME_ACTION_UNSPECIFIED;
case "TextInputAction.done":
return EditorInfo.IME_ACTION_DONE;
case "TextInputAction.go":
return EditorInfo.IME_ACTION_GO;
case "TextInputAction.search":
return EditorInfo.IME_ACTION_SEARCH;
case "TextInputAction.send":
return EditorInfo.IME_ACTION_SEND;
case "TextInputAction.next":
return EditorInfo.IME_ACTION_NEXT;
case "TextInputAction.previous":
return EditorInfo.IME_ACTION_PREVIOUS;
default:
// Present default key if bad input type is given.
return EditorInfo.IME_ACTION_UNSPECIFIED;
}
}
public InputConnection createInputConnection(FlutterView view, EditorInfo outAttrs)

View File

@ -8,7 +8,16 @@
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, FlutterTextInputAction) {
FlutterTextInputActionUnspecified,
FlutterTextInputActionDone,
FlutterTextInputActionGo,
FlutterTextInputActionSend,
FlutterTextInputActionSearch,
FlutterTextInputActionNext,
FlutterTextInputActionContinue,
FlutterTextInputActionJoin,
FlutterTextInputActionRoute,
FlutterTextInputActionEmergencyCall,
FlutterTextInputActionNewline,
};

View File

@ -5,6 +5,7 @@
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
#include <UIKit/UIKit.h>
#include <Foundation/Foundation.h>
static const char _kTextAffinityDownstream[] = "TextAffinity.downstream";
static const char _kTextAffinityUpstream[] = "TextAffinity.upstream";
@ -30,9 +31,46 @@ static UIKeyboardType ToUIKeyboardType(NSDictionary* type) {
}
static UIReturnKeyType ToUIReturnKeyType(NSString* inputType) {
if ([inputType isEqualToString:@"TextInputType.multiline"])
// Where did the term "unspecified" come from? iOS has a "default" and Android
// has "unspecified." These 2 terms seem to mean the same thing but we need
// to pick just one. "unspecified" was chosen because "default" is often a
// reserved word in languages with switch statements (dart, java, etc).
if ([inputType isEqualToString:@"TextInputAction.unspecified"])
return UIReturnKeyDefault;
return UIReturnKeyDone;
if ([inputType isEqualToString:@"TextInputAction.done"])
return UIReturnKeyDone;
if ([inputType isEqualToString:@"TextInputAction.go"])
return UIReturnKeyGo;
if ([inputType isEqualToString:@"TextInputAction.send"])
return UIReturnKeySend;
if ([inputType isEqualToString:@"TextInputAction.search"])
return UIReturnKeySearch;
if ([inputType isEqualToString:@"TextInputAction.next"])
return UIReturnKeyNext;
if (@available(iOS 9.0, *))
if ([inputType isEqualToString:@"TextInputAction.continueAction"])
return UIReturnKeyContinue;
if ([inputType isEqualToString:@"TextInputAction.join"])
return UIReturnKeyJoin;
if ([inputType isEqualToString:@"TextInputAction.route"])
return UIReturnKeyRoute;
if ([inputType isEqualToString:@"TextInputAction.emergencyCall"])
return UIReturnKeyEmergencyCall;
if ([inputType isEqualToString:@"TextInputAction.newline"])
return UIReturnKeyDefault;
// Present default key if bad input type is given.
return UIReturnKeyDefault;
}
static UITextAutocapitalizationType ToUITextAutocapitalizationType(NSString* inputType) {
@ -277,14 +315,52 @@ static UITextAutocapitalizationType ToUITextAutocapitalizationType(NSString* inp
}
- (BOOL)shouldChangeTextInRange:(UITextRange*)range replacementText:(NSString*)text {
if (self.returnKeyType == UIReturnKeyDone && [text isEqualToString:@"\n"]) {
[self resignFirstResponder];
[self removeFromSuperview];
[_textInputDelegate performAction:FlutterTextInputActionDone withClient:_textInputClient];
if (self.returnKeyType == UIReturnKeyDefault && [text isEqualToString:@"\n"]) {
[_textInputDelegate performAction:FlutterTextInputActionNewline withClient:_textInputClient];
return YES;
}
if ([text isEqualToString:@"\n"]) {
FlutterTextInputAction action;
switch (self.returnKeyType) {
case UIReturnKeyDefault:
action = FlutterTextInputActionUnspecified;
break;
case UIReturnKeyDone:
action = FlutterTextInputActionDone;
break;
case UIReturnKeyGo:
action = FlutterTextInputActionGo;
break;
case UIReturnKeySend:
action = FlutterTextInputActionSend;
break;
case UIReturnKeySearch:
case UIReturnKeyGoogle:
case UIReturnKeyYahoo:
action = FlutterTextInputActionSearch;
break;
case UIReturnKeyNext:
action = FlutterTextInputActionNext;
break;
case UIReturnKeyContinue:
action = FlutterTextInputActionContinue;
break;
case UIReturnKeyJoin:
action = FlutterTextInputActionJoin;
break;
case UIReturnKeyRoute:
action = FlutterTextInputActionRoute;
break;
case UIReturnKeyEmergencyCall:
action = FlutterTextInputActionEmergencyCall;
break;
}
[_textInputDelegate performAction:action withClient:_textInputClient];
return NO;
}
if (self.returnKeyType == UIReturnKeyDefault && [text isEqualToString:@"\n"])
[_textInputDelegate performAction:FlutterTextInputActionNewline withClient:_textInputClient];
return YES;
}
@ -612,7 +688,7 @@ static UITextAutocapitalizationType ToUITextAutocapitalizationType(NSString* inp
- (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configuration {
NSDictionary* inputType = configuration[@"inputType"];
_view.keyboardType = ToUIKeyboardType(inputType);
_view.returnKeyType = ToUIReturnKeyType(inputType[@"name"]);
_view.returnKeyType = ToUIReturnKeyType(configuration[@"inputAction"]);
_view.autocapitalizationType = ToUITextAutocapitalizationType(inputType[@"name"]);
_view.secureTextEntry = [configuration[@"obscureText"] boolValue];
NSString* autocorrect = configuration[@"autocorrect"];

View File

@ -717,9 +717,40 @@ static inline blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* to
- (void)performAction:(FlutterTextInputAction)action withClient:(int)client {
NSString* actionString;
switch (action) {
case FlutterTextInputActionUnspecified:
// Where did the term "unspecified" come from? iOS has a "default" and Android
// has "unspecified." These 2 terms seem to mean the same thing but we need
// to pick just one. "unspecified" was chosen because "default" is often a
// reserved word in languages with switch statements (dart, java, etc).
actionString = @"TextInputAction.unspecified";
break;
case FlutterTextInputActionDone:
actionString = @"TextInputAction.done";
break;
case FlutterTextInputActionGo:
actionString = @"TextInputAction.go";
break;
case FlutterTextInputActionSend:
actionString = @"TextInputAction.send";
break;
case FlutterTextInputActionSearch:
actionString = @"TextInputAction.search";
break;
case FlutterTextInputActionNext:
actionString = @"TextInputAction.next";
break;
case FlutterTextInputActionContinue:
actionString = @"TextInputAction.continue";
break;
case FlutterTextInputActionJoin:
actionString = @"TextInputAction.join";
break;
case FlutterTextInputActionRoute:
actionString = @"TextInputAction.route";
break;
case FlutterTextInputActionEmergencyCall:
actionString = @"TextInputAction.emergencyCall";
break;
case FlutterTextInputActionNewline:
actionString = @"TextInputAction.newline";
break;