Skip to content

Commit

Permalink
add text capitalization support to ios and android (flutter#5752)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonahwilliams authored Jul 20, 2018
1 parent 482469b commit d1c71e5
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
* Android implementation of the text input plugin.
*/
public class TextInputPlugin implements MethodCallHandler {

private final FlutterView mView;
private final InputMethodManager mImm;
private final MethodChannel mFlutterChannel;
Expand All @@ -37,9 +36,9 @@ public class TextInputPlugin implements MethodCallHandler {

public TextInputPlugin(FlutterView view) {
mView = view;
mImm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
mFlutterChannel = new MethodChannel(view, "flutter/textinput",
JSONMethodCodec.INSTANCE);
mImm = (InputMethodManager) view.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
mFlutterChannel = new MethodChannel(view, "flutter/textinput", JSONMethodCodec.INSTANCE);
mFlutterChannel.setMethodCallHandler(this);
}

Expand Down Expand Up @@ -72,22 +71,17 @@ public void onMethodCall(MethodCall call, Result result) {
}
}

private static int inputTypeFromTextInputType(
JSONObject type, boolean obscureText, boolean autocorrect) throws JSONException {

private static int inputTypeFromTextInputType(JSONObject type, boolean obscureText,
boolean autocorrect, String textCapitalization) throws JSONException {
String inputType = type.getString("name");
if (inputType.equals("TextInputType.datetime"))
return InputType.TYPE_CLASS_DATETIME;
if (inputType.equals("TextInputType.datetime")) return InputType.TYPE_CLASS_DATETIME;
if (inputType.equals("TextInputType.number")) {
int textType = InputType.TYPE_CLASS_NUMBER;
if (type.optBoolean("signed"))
textType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
if (type.optBoolean("decimal"))
textType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
if (type.optBoolean("signed")) textType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
if (type.optBoolean("decimal")) textType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
return textType;
}
if (inputType.equals("TextInputType.phone"))
return InputType.TYPE_CLASS_PHONE;
if (inputType.equals("TextInputType.phone")) return InputType.TYPE_CLASS_PHONE;

int textType = InputType.TYPE_CLASS_TEXT;
if (inputType.equals("TextInputType.multiline"))
Expand All @@ -101,9 +95,13 @@ else if (inputType.equals("TextInputType.url"))
textType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
textType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
} else {
if (autocorrect)
textType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
if (inputType.equals("TextInputType.text") || inputType.equals("TextInputType.multiline"))
if (autocorrect) textType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
}
if (textCapitalization.equals("TextCapitalization.characters")) {
textType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
} else if (textCapitalization.equals("TextCapitalization.words")) {
textType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS;
} else if (textCapitalization.equals("TextCapitalization.sentences")) {
textType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
}
return textType;
Expand Down Expand Up @@ -136,22 +134,21 @@ private static int inputActionFromTextInputAction(String inputAction) {
}

public InputConnection createInputConnection(FlutterView view, EditorInfo outAttrs)
throws JSONException {
if (mClient == 0)
return null;

outAttrs.inputType = inputTypeFromTextInputType(
mConfiguration.getJSONObject("inputType"),
mConfiguration.optBoolean("obscureText"),
mConfiguration.optBoolean("autocorrect", true));
throws JSONException {
if (mClient == 0) return null;

outAttrs.inputType = inputTypeFromTextInputType(mConfiguration.getJSONObject("inputType"),
mConfiguration.optBoolean("obscureText"),
mConfiguration.optBoolean("autocorrect", true),
mConfiguration.getString("textCapitalization"));
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;
? EditorInfo.IME_ACTION_NONE
: EditorInfo.IME_ACTION_DONE;
} else {
enterAction = inputActionFromTextInputAction(mConfiguration.getString("inputAction"));
}
Expand All @@ -161,7 +158,8 @@ public InputConnection createInputConnection(FlutterView view, EditorInfo outAtt
}
outAttrs.imeOptions |= enterAction;

InputConnectionAdaptor connection = new InputConnectionAdaptor(view, mClient, mFlutterChannel, mEditable);
InputConnectionAdaptor connection =
new InputConnectionAdaptor(view, mClient, mFlutterChannel, mEditable);
outAttrs.initialSelStart = Selection.getSelectionStart(mEditable);
outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable);

Expand Down Expand Up @@ -189,25 +187,21 @@ private void setTextInputClient(FlutterView view, int client, JSONObject configu
private void applyStateToSelection(JSONObject state) throws JSONException {
int selStart = state.getInt("selectionBase");
int selEnd = state.getInt("selectionExtent");
if (selStart >= 0 && selStart <= mEditable.length() &&
selEnd >= 0 && selEnd <= mEditable.length()) {
if (selStart >= 0 && selStart <= mEditable.length() && selEnd >= 0
&& selEnd <= mEditable.length()) {
Selection.setSelection(mEditable, selStart, selEnd);
} else {
Selection.removeSelection(mEditable);
}
}

private void setTextInputEditingState(FlutterView view, JSONObject state)
throws JSONException {
if (!mRestartInputPending &&
state.getString("text").equals(mEditable.toString())) {
private void setTextInputEditingState(FlutterView view, JSONObject state) throws JSONException {
if (!mRestartInputPending && state.getString("text").equals(mEditable.toString())) {
applyStateToSelection(state);
mImm.updateSelection(
mView,
Math.max(Selection.getSelectionStart(mEditable), 0),
Math.max(Selection.getSelectionEnd(mEditable), 0),
BaseInputConnection.getComposingSpanStart(mEditable),
BaseInputConnection.getComposingSpanEnd(mEditable));
mImm.updateSelection(mView, Math.max(Selection.getSelectionStart(mEditable), 0),
Math.max(Selection.getSelectionEnd(mEditable), 0),
BaseInputConnection.getComposingSpanStart(mEditable),
BaseInputConnection.getComposingSpanEnd(mEditable));
} else {
mEditable.replace(0, mEditable.length(), state.getString("text"));
applyStateToSelection(state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"

#include <UIKit/UIKit.h>
#include <Foundation/Foundation.h>
#include <UIKit/UIKit.h>

static const char _kTextAffinityDownstream[] = "TextAffinity.downstream";
static const char _kTextAffinityUpstream[] = "TextAffinity.upstream";
Expand All @@ -30,6 +30,18 @@ static UIKeyboardType ToUIKeyboardType(NSDictionary* type) {
return UIKeyboardTypeDefault;
}

static UITextAutocapitalizationType ToUITextAutoCapitalizationType(NSDictionary* type) {
NSString* textCapitalization = type[@"textCapitalization"];
if ([textCapitalization isEqualToString:@"TextCapitalization.characters"]) {
return UITextAutocapitalizationTypeAllCharacters;
} else if ([textCapitalization isEqualToString:@"TextCapitalization.sentences"]) {
return UITextAutocapitalizationTypeSentences;
} else if ([textCapitalization isEqualToString:@"TextCapitalization.words"]) {
return UITextAutocapitalizationTypeWords;
}
return UITextAutocapitalizationTypeNone;
}

static UIReturnKeyType ToUIReturnKeyType(NSString* inputType) {
// 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
Expand Down Expand Up @@ -73,14 +85,6 @@ static UIReturnKeyType ToUIReturnKeyType(NSString* inputType) {
return UIReturnKeyDefault;
}

static UITextAutocapitalizationType ToUITextAutocapitalizationType(NSString* inputType) {
if ([inputType isEqualToString:@"TextInputType.text"])
return UITextAutocapitalizationTypeSentences;
if ([inputType isEqualToString:@"TextInputType.multiline"])
return UITextAutocapitalizationTypeSentences;
return UITextAutocapitalizationTypeNone;
}

#pragma mark - FlutterTextPosition

@implementation FlutterTextPosition
Expand Down Expand Up @@ -690,10 +694,10 @@ - (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configur
NSString* keyboardAppearance = configuration[@"keyboardAppearance"];
_view.keyboardType = ToUIKeyboardType(inputType);
_view.returnKeyType = ToUIReturnKeyType(configuration[@"inputAction"]);
_view.autocapitalizationType = ToUITextAutocapitalizationType(inputType[@"name"]);
_view.autocapitalizationType = ToUITextAutoCapitalizationType(configuration);
if ([keyboardAppearance isEqualToString:@"Brightness.dark"]) {
_view.keyboardAppearance = UIKeyboardAppearanceDark;
} else if ([keyboardAppearance isEqualToString:@"Brightness.light"]) {
} else if ([keyboardAppearance isEqualToString:@"Brightness.light"]) {
_view.keyboardAppearance = UIKeyboardAppearanceLight;
} else {
_view.keyboardAppearance = UIKeyboardAppearanceDefault;
Expand Down

0 comments on commit d1c71e5

Please sign in to comment.