浏览代码

android keyboard

/main
fzhangtj 6 年前
当前提交
38eea642
共有 18 个文件被更改,包括 824 次插入8 次删除
  1. 15
      Runtime/engine/UIWidgetsMessageManager.cs
  2. 57
      Runtime/service/keyboard.cs
  3. 14
      Runtime/service/text_input.cs
  4. 5
      Runtime/widgets/editable_text.cs
  5. 8
      Runtime/Plugins/platform/android.meta
  6. 45
      Runtime/Plugins/platform/android/UIWidgetsMessageManager.java
  7. 31
      Runtime/Plugins/platform/android/UIWidgetsMessageManager.java.meta
  8. 5
      Runtime/Plugins/platform/android/Utils.java
  9. 31
      Runtime/Plugins/platform/android/Utils.java.meta
  10. 8
      Runtime/Plugins/platform/android/editing.meta
  11. 215
      Runtime/Plugins/platform/android/editing/InputConnectionAdaptor.java
  12. 31
      Runtime/Plugins/platform/android/editing/InputConnectionAdaptor.java.meta
  13. 257
      Runtime/Plugins/platform/android/editing/TextInputPlugin.java
  14. 31
      Runtime/Plugins/platform/android/editing/TextInputPlugin.java.meta
  15. 48
      Runtime/Plugins/platform/android/editing/TextInputView.java
  16. 31
      Runtime/Plugins/platform/android/editing/TextInputView.java.meta

15
Runtime/engine/UIWidgetsMessageManager.cs


var name = this.gameObject.name;
if (name != this._lastObjectName) {
this._lastObjectName = name;
#if UNITY_IOS
#if UNITY_IOS || UNITY_ANDROID
if (!Application.isEditor) {
UIWidgetsMessageSetObjectName(this._lastObjectName);
}

#if UNITY_IOS
[DllImport("__Internal")]
static extern void UIWidgetsMessageSetObjectName(string objectName);
#elif UNITY_ANDROID
static void UIWidgetsMessageSetObjectName(string objectName) {
using (
AndroidJavaClass managerClass = new AndroidJavaClass("com.unity.uiwidgets.plugin.UIWidgetsMessageManager")
) {
using (
AndroidJavaObject managerInstance = managerClass.CallStatic<AndroidJavaObject>("getInstance")
) {
managerInstance.Call("SetObjectName", objectName);
}
}
}
#endif
}

57
Runtime/service/keyboard.cs


this._keyboard.text,
this._keyboard.canGetSelection
? new TextSelection(keyboardSelection.start, keyboardSelection.end)
: this._value.selection
: TextSelection.collapsed(0)
this._value = newValue;
if (changed) {
Window.instance.run(() => {

}
}
#if UNITY_IOS
internal static extern float UIWidgetsTextInputShow();
internal static extern void UIWidgetsTextInputShow();
internal static extern float UIWidgetsTextInputHide();
internal static extern void UIWidgetsTextInputHide();
internal static extern float UIWidgetsTextInputSetClient(int client, string configuration);
internal static extern void UIWidgetsTextInputSetClient(int client, string configuration);
internal static extern float UIWidgetsTextInputSetTextInputEditingState(string jsonText); // also send to client ?
internal static extern void UIWidgetsTextInputSetTextInputEditingState(string jsonText); // also send to client ?
internal static extern float UIWidgetsTextInputClearTextInputClient();
internal static extern void UIWidgetsTextInputClearTextInputClient();
#elif UNITY_ANDROID
internal static void UIWidgetsTextInputShow() {
using (
AndroidJavaClass pluginClass = new AndroidJavaClass("com.unity.uiwidgets.plugin.editing.TextInputPlugin")
) {
pluginClass.CallStatic("show");
}
}
internal static void UIWidgetsTextInputHide() {
using (
AndroidJavaClass pluginClass = new AndroidJavaClass("com.unity.uiwidgets.plugin.editing.TextInputPlugin")
) {
pluginClass.CallStatic("hide");
}
}
internal static void UIWidgetsTextInputSetClient(int client, string configuration) {
using (
AndroidJavaClass pluginClass = new AndroidJavaClass("com.unity.uiwidgets.plugin.editing.TextInputPlugin")
) {
pluginClass.CallStatic("setClient", client, configuration);
}
}
internal static void UIWidgetsTextInputSetTextInputEditingState(string jsonText) {
using (
AndroidJavaClass pluginClass = new AndroidJavaClass("com.unity.uiwidgets.plugin.editing.TextInputPlugin")
) {
pluginClass.CallStatic("setEditingState", jsonText);
}
}
internal static void UIWidgetsTextInputClearTextInputClient() {
using (
AndroidJavaClass pluginClass = new AndroidJavaClass("com.unity.uiwidgets.plugin.editing.TextInputPlugin")
) {
pluginClass.CallStatic("clearClient");
}
}
#endif
#endif
}

14
Runtime/service/text_input.cs


scrollPageDown,
}
public enum TextCapitalization {
words,
sentences,
characters,
none
}
Brightness keyboardAppearance = Brightness.light, TextCapitalization textCapitalization = TextCapitalization.none,
this.textCapitalization = textCapitalization;
this.keyboardAppearance = keyboardAppearance;
this.unityTouchKeyboard = unityTouchKeyboard;
}

public readonly TextInputAction inputAction;
public readonly TextCapitalization textCapitalization;
public readonly Brightness keyboardAppearance;
public readonly bool unityTouchKeyboard;
public JSONNode toJson() {

json["autocorrect"] = this.autocorrect;
json["inputAction"] = $"TextInputAction.{this.inputAction.ToString()}";
json["unityTouchKeyboard"] = this.unityTouchKeyboard;
json["textCapitalization"] = $"TextCapitalization.{this.textCapitalization.ToString()}";
json["keyboardAppearance"] = $"Brightness.{this.keyboardAppearance.ToString()}";
return json;
}
}

5
Runtime/widgets/editable_text.cs


public readonly TextDirection? textDirection;
public readonly TextCapitalization textCapitalization;
public readonly float? textScaleFactor;
public readonly Color cursorColor;

float? textScaleFactor = null, int? maxLines = 1,
bool autofocus = false, Color selectionColor = null, TextSelectionControls selectionControls = null,
TextInputType keyboardType = null, TextInputAction? textInputAction = null,
TextCapitalization textCapitalization = TextCapitalization.none,
ValueChanged<string> onChanged = null, VoidCallback onEditingComplete = null,
ValueChanged<string> onSubmitted = null, SelectionChangedCallback onSelectionChanged = null,
List<TextInputFormatter> inputFormatters = null, bool rendererIgnoresPointer = false,

this.textDirection = textDirection;
this.textScaleFactor = textScaleFactor;
this.textInputAction = textInputAction;
this.textCapitalization = textCapitalization;
this.cursorColor = cursorColor;
this.maxLines = maxLines;
this.autofocus = autofocus;

inputAction: this.widget.textInputAction ?? ((this.widget.keyboardType == TextInputType.multiline)
? TextInputAction.newline
: TextInputAction.done),
textCapitalization: this.widget.textCapitalization,
unityTouchKeyboard: this.widget.unityTouchKeyboard
));

8
Runtime/Plugins/platform/android.meta


fileFormatVersion: 2
guid: f583d2115d43b4c77b104bc35805fefb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

45
Runtime/Plugins/platform/android/UIWidgetsMessageManager.java


package com.unity.uiwidgets.plugin;
import android.util.Log;
import com.unity3d.player.UnityPlayer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
import static com.unity.uiwidgets.plugin.Utils.TAG;
public class UIWidgetsMessageManager {
private static UIWidgetsMessageManager _instance;
private String gameObjectName;
public static UIWidgetsMessageManager getInstance() {
if (_instance == null) {
_instance = new UIWidgetsMessageManager();
}
return _instance;
}
public void SetObjectName(String name) {
gameObjectName = name;
}
public void UIWidgetsMethodMessage(String channel, String method, List<Object> args) {
JSONObject object = new JSONObject();
try {
object.put("channel", channel);
object.put("method", method);
object.put("args", new JSONArray(args));
UnityPlayer.UnitySendMessage(gameObjectName, "OnUIWidgetsMethodMessage", object.toString());
} catch (JSONException e) {
Log.e(TAG, "error parse json", e);
}
}
}

31
Runtime/Plugins/platform/android/UIWidgetsMessageManager.java.meta


fileFormatVersion: 2
guid: 6349deb4a47a44388806597a144b9bfd
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

5
Runtime/Plugins/platform/android/Utils.java


package com.unity.uiwidgets.plugin;
public class Utils {
public static final String TAG = "UIWidgets";
}

31
Runtime/Plugins/platform/android/Utils.java.meta


fileFormatVersion: 2
guid: 6da51e571970348b59198a520437c8b0
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/Plugins/platform/android/editing.meta


fileFormatVersion: 2
guid: 3483e1b60ba954551952665afcccb2c8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

215
Runtime/Plugins/platform/android/editing/InputConnectionAdaptor.java


// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.unity.uiwidgets.plugin.editing;
import android.content.Context;
import android.text.Editable;
import android.text.Selection;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import com.unity.uiwidgets.plugin.UIWidgetsMessageManager;
import java.util.Arrays;
import java.util.HashMap;
class InputConnectionAdaptor extends BaseInputConnection {
private View mTextInputView;
private final int mClient;
private final Editable mEditable;
private int mBatchCount;
private InputMethodManager mImm;
public InputConnectionAdaptor(View view, int client,
Editable editable) {
super(view, true);
mTextInputView = view;
mClient = client;
mEditable = editable;
mBatchCount = 0;
mImm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
}
// Send the current state of the editable to Flutter.
private void updateEditingState() {
// If the IME is in the middle of a batch edit, then wait until it completes.
if (mBatchCount > 0)
return;
int selectionStart = Selection.getSelectionStart(mEditable);
int selectionEnd = Selection.getSelectionEnd(mEditable);
int composingStart = BaseInputConnection.getComposingSpanStart(mEditable);
int composingEnd = BaseInputConnection.getComposingSpanEnd(mEditable);
mImm.updateSelection(mTextInputView,
selectionStart, selectionEnd,
composingStart, composingEnd);
HashMap<Object, Object> state = new HashMap<Object, Object>();
state.put("text", mEditable.toString());
state.put("selectionBase", selectionStart);
state.put("selectionExtent", selectionEnd);
state.put("composingBase", composingStart);
state.put("composingExtent", composingEnd);
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.updateEditingState",
Arrays.asList(mClient, state));
}
@Override
public Editable getEditable() {
return mEditable;
}
@Override
public boolean beginBatchEdit() {
mBatchCount++;
return super.beginBatchEdit();
}
@Override
public boolean endBatchEdit() {
boolean result = super.endBatchEdit();
mBatchCount--;
updateEditingState();
return result;
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
boolean result = super.commitText(text, newCursorPosition);
updateEditingState();
return result;
}
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
if (Selection.getSelectionStart(mEditable) == -1)
return true;
boolean result = super.deleteSurroundingText(beforeLength, afterLength);
updateEditingState();
return result;
}
@Override
public boolean setComposingRegion(int start, int end) {
boolean result = super.setComposingRegion(start, end);
updateEditingState();
return result;
}
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
boolean result;
if (text.length() == 0) {
result = super.commitText(text, newCursorPosition);
} else {
result = super.setComposingText(text, newCursorPosition);
}
updateEditingState();
return result;
}
@Override
public boolean setSelection(int start, int end) {
boolean result = super.setSelection(start, end);
updateEditingState();
return result;
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
int selStart = Selection.getSelectionStart(mEditable);
int selEnd = Selection.getSelectionEnd(mEditable);
if (selEnd > selStart) {
// Delete the selection.
Selection.setSelection(mEditable, selStart);
mEditable.delete(selStart, selEnd);
updateEditingState();
return true;
} else if (selStart > 0) {
// Delete to the left of the cursor.
int newSel = Math.max(selStart - 1, 0);
Selection.setSelection(mEditable, newSel);
mEditable.delete(newSel, selStart);
updateEditingState();
return true;
}
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {
int selStart = Selection.getSelectionStart(mEditable);
int newSel = Math.max(selStart - 1, 0);
setSelection(newSel, newSel);
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {
int selStart = Selection.getSelectionStart(mEditable);
int newSel = Math.min(selStart + 1, mEditable.length());
setSelection(newSel, newSel);
return true;
} else {
// Enter a character.
int character = event.getUnicodeChar();
if (character != 0) {
int selStart = Math.max(0, Selection.getSelectionStart(mEditable));
int selEnd = Math.max(0, Selection.getSelectionEnd(mEditable));
if (selEnd != selStart)
mEditable.delete(selStart, selEnd);
mEditable.insert(selStart, String.valueOf((char) character));
setSelection(selStart + 1, selStart + 1);
updateEditingState();
}
return true;
}
}
return false;
}
@Override
public boolean performEditorAction(int actionCode) {
switch (actionCode) {
// TODO(mattcarroll): is newline an appropriate action for "none"?
case EditorInfo.IME_ACTION_NONE:
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.newline"));
break;
case EditorInfo.IME_ACTION_UNSPECIFIED:
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.unspecified"));
break;
case EditorInfo.IME_ACTION_GO:
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.go"));
break;
case EditorInfo.IME_ACTION_SEARCH:
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.search"));
break;
case EditorInfo.IME_ACTION_SEND:
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.send"));
break;
case EditorInfo.IME_ACTION_NEXT:
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.next"));
break;
case EditorInfo.IME_ACTION_PREVIOUS:
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.previous"));
break;
default:
case EditorInfo.IME_ACTION_DONE:
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction",
Arrays.asList(mClient, "TextInputAction.done"));
break;
}
return true;
}
}

31
Runtime/Plugins/platform/android/editing/InputConnectionAdaptor.java.meta


fileFormatVersion: 2
guid: ee71437b1f6244476b59360f556db8b7
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

257
Runtime/Plugins/platform/android/editing/TextInputPlugin.java


// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.unity.uiwidgets.plugin.editing;
import android.content.Context;
import android.text.Editable;
import android.text.InputType;
import android.text.Selection;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import com.unity3d.player.UnityPlayer;
import org.json.JSONException;
import org.json.JSONObject;
import static com.unity.uiwidgets.plugin.Utils.TAG;
public class TextInputPlugin {
private final TextInputView mView;
private final InputMethodManager mImm;
private int mClient = 0;
private JSONObject mConfiguration;
private Editable mEditable;
private boolean mRestartInputPending;
private static TextInputPlugin _instance;
public static TextInputPlugin getInstance() {
if (_instance == null) {
_instance = new TextInputPlugin();
}
return _instance;
}
public TextInputPlugin() {
ViewGroup contentView = (ViewGroup)UnityPlayer.currentActivity.findViewById(android.R.id.content);
mView = new TextInputView(UnityPlayer.currentActivity);
contentView.addView(mView, 0, 0);
mImm = (InputMethodManager) mView.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
}
public static void show() {
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
TextInputPlugin plugin = getInstance();
plugin.showTextInput(plugin.mView);
}
});
}
public static void hide() {
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
TextInputPlugin plugin = getInstance();
plugin.hideTextInput(plugin.mView);
}
});
}
public static void setClient(int client, String configurationJson) {
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject configuration = new JSONObject(configurationJson);
TextInputPlugin plugin = getInstance();
plugin.setTextInputClient(plugin.mView, client, configuration);
} catch (JSONException e) {
Log.e(TAG, "error parse json", e);
}
}
});
}
public static void setEditingState(String stateJson) {
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
TextInputPlugin plugin = getInstance();
JSONObject state = new JSONObject(stateJson);
plugin.setTextInputEditingState(plugin.mView, state);
} catch (JSONException e) {
Log.e(TAG, "error parse json", e);
}
}
});
}
public static void clearClient() {
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
TextInputPlugin plugin = getInstance();
plugin.clearTextInputClient();
}
});
}
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.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;
return textType;
}
if (inputType.equals("TextInputType.phone")) return InputType.TYPE_CLASS_PHONE;
int textType = InputType.TYPE_CLASS_TEXT;
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;
if (obscureText) {
// Note: both required. Some devices ignore TYPE_TEXT_FLAG_NO_SUGGESTIONS.
textType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
textType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
} else {
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;
}
private static int inputActionFromTextInputAction(String inputAction) {
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(View view, EditorInfo outAttrs)
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;
} 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, mEditable);
outAttrs.initialSelStart = Selection.getSelectionStart(mEditable);
outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable);
return connection;
}
private void showTextInput(View view) {
view.requestFocus();
mImm.showSoftInput(view, 0);
}
private void hideTextInput(View view) {
mImm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
}
private void setTextInputClient(View view, int client, JSONObject configuration) {
mClient = client;
mConfiguration = configuration;
mEditable = Editable.Factory.getInstance().newEditable("");
// setTextInputClient will be followed by a call to setTextInputEditingState.
// Do a restartInput at that time.
mRestartInputPending = true;
}
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()) {
Selection.setSelection(mEditable, selStart, selEnd);
} else {
Selection.removeSelection(mEditable);
}
}
private void setTextInputEditingState(View 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));
} else {
mEditable.replace(0, mEditable.length(), state.getString("text"));
applyStateToSelection(state);
mImm.restartInput(view);
mRestartInputPending = false;
}
}
private void clearTextInputClient() {
mClient = 0;
}
}

31
Runtime/Plugins/platform/android/editing/TextInputPlugin.java.meta


fileFormatVersion: 2
guid: 867d39559763e4ea9b82b9a5987a1930
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

48
Runtime/Plugins/platform/android/editing/TextInputView.java


package com.unity.uiwidgets.plugin.editing;
import android.content.Context;
import android.util.Log;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import org.json.JSONException;
import static com.unity.uiwidgets.plugin.Utils.TAG;
public class TextInputView extends View {
private InputConnection mLastInputConnection;
private final InputMethodManager mImm;
public TextInputView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
Log.i(TAG, "onCreateInputConnection");
try {
mLastInputConnection = TextInputPlugin.getInstance().createInputConnection(this, outAttrs);
return mLastInputConnection;
} catch (JSONException e) {
Log.e(TAG, "Failed to create input connection", e);
return null;
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getDeviceId() != KeyCharacterMap.VIRTUAL_KEYBOARD) {
if (mLastInputConnection != null && mImm.isAcceptingText()) {
mLastInputConnection.sendKeyEvent(event);
}
}
return super.onKeyDown(keyCode, event);
}
}

31
Runtime/Plugins/platform/android/editing/TextInputView.java.meta


fileFormatVersion: 2
guid: acd0b1bb7c09d4b5ca41554aa9c30257
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存