siyao
4 年前
当前提交
431751b4
共有 14 个文件被更改,包括 681 次插入 和 33 次删除
-
4com.unity.uiwidgets/Editor/UIWidgetsPanelEditor.cs
-
14com.unity.uiwidgets/Runtime/Plugins/Android/UIWidgetsViewController.java
-
3com.unity.uiwidgets/Runtime/Plugins/Android/Utils.java
-
36com.unity.uiwidgets/Runtime/engine/UIWidgetsMessageManager.cs
-
3com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanel.cs
-
15com.unity.uiwidgets/Runtime/services/keyboard.cs
-
3com.unity.uiwidgets/Runtime/services/text_input.cs
-
4com.unity.uiwidgets/Runtime/ui2/hooks.cs
-
233com.unity.uiwidgets/Runtime/Plugins/Android/InputConnectionAdaptor.java
-
31com.unity.uiwidgets/Runtime/Plugins/Android/InputConnectionAdaptor.java.meta
-
258com.unity.uiwidgets/Runtime/Plugins/Android/TextInputPlugin.java
-
31com.unity.uiwidgets/Runtime/Plugins/Android/TextInputPlugin.java.meta
-
48com.unity.uiwidgets/Runtime/Plugins/Android/TextInputView.java
-
31com.unity.uiwidgets/Runtime/Plugins/Android/TextInputView.java.meta
|
|||
// 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); |
|||
String text = mEditable.toString(); |
|||
if(selStart >= 0 && selStart < text.length() && isTrailSurrogate(text.charAt(selStart))) { |
|||
selStart++; |
|||
} |
|||
if(selEnd >= 0 && selEnd < text.length() && isTrailSurrogate(text.charAt(selEnd))) { |
|||
selEnd++; |
|||
} |
|||
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); |
|||
if(selStart >= 2 && isTrailSurrogate(text.charAt(selStart-1))) |
|||
newSel = selStart - 2; |
|||
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; |
|||
} |
|||
|
|||
private boolean isLeadSurrogate(int c) { |
|||
return (c & 0xfffffc00) == 0xd800; |
|||
} |
|||
|
|||
|
|||
private boolean isTrailSurrogate(int c) { |
|||
return (c & 0xfffffc00) == 0xdc00; |
|||
} |
|||
} |
|
|||
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: |
|
|||
// 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); |
|||
mView.requestFocus(); |
|||
contentView.addView(mView, 1, 1); |
|||
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; |
|||
} |
|||
} |
|
|||
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: |
|
|||
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); |
|||
} |
|||
} |
|
|||
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: |
撰写
预览
正在加载...
取消
保存
Reference in new issue