下面列出了怎么用android.view.inputmethod.InputConnection的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
final InputConnection ic = super.onCreateInputConnection(editorInfo);
EditorInfoCompat.setContentMimeTypes(editorInfo, mSupportedMimeTypes);
final InputConnectionCompat.OnCommitContentListener callback =
new InputConnectionCompat.OnCommitContentListener() {
@Override
public boolean onCommitContent(
InputContentInfoCompat inputContentInfo, int flags, Bundle opts) {
if (mListener != null) {
return mListener.onCommitContent(
inputContentInfo, flags, opts, mSupportedMimeTypes);
}
return false;
}
};
if (ic != null) {
return InputConnectionCompat.createWrapper(ic, editorInfo, callback);
}
return null;
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
final InputConnection ic = super.onCreateInputConnection(outAttrs);
if ( ic == null ) {
return null;
}
if ( outAttrs.hintText == null ) {
// If we don't have a hint and our parent is a TextInputLayout, use it's hint for the
// EditorInfo. This allows us to display a hint in 'extract mode'.
final ViewParent parent = getParent();
if (parent instanceof TextInputLayout) {
outAttrs.hintText = ((TextInputLayout) parent).getHint();
}
}
return ic;
}
/**
* Keyboard.OnKeyboardListener method
* <p>
* Delete back one visible character before cursor. Extra control
* characters like FVS, MVS, ZWJ, etc. may also be deleted.
*/
@Override
public void onBackspace() {
InputConnection ic = getInputConnection();
if (ic == null) return;
if (!TextUtils.isEmpty(mComposing)) {
ic.commitText(mComposing, 1);
mComposing = "";
}
if (hasSelection()) {
doBackspace();
return;
}
CharSequence previousFourChars = getTextBeforeCursor(4);
backspaceFromEndOf(previousFourChars);
clearCandidates();
}
void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {
if (!restarting) {
doFinishInput();
}
mInputStarted = true;
mStartedInputConnection = ic;
mInputEditorInfo = attribute;
initialize();
if (DEBUG) Log.v(TAG, "CALL: onStartInput");
onStartInput(attribute, restarting);
if (mWindowVisible) {
if (mShowInputRequested) {
if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
mInputViewStarted = true;
onStartInputView(mInputEditorInfo, restarting);
startExtractingText(true);
} else if (mCandidatesVisibility == View.VISIBLE) {
if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
mCandidatesViewStarted = true;
onStartCandidatesView(mInputEditorInfo, restarting);
}
}
}
public KCommands(
KboardIME ime,
InputConnection ic,
EditorInfo ei,
List<String> keys,
boolean autoSpace,
boolean passiveAggressive) {
inputConnection = ic;
inputEditor = ei;
mAutoSpace = autoSpace;
mPassiveAggressive = passiveAggressive;
List<String> mKeys = keys;
mIme = ime;
for (String key: mKeys) {
if (!(key.startsWith("/") && key.contains("!"))) {
mTextKeys.add(key);
} else {
mCommandKeys.put(key.split("!", 2)[0].substring(1), key.split("!", 2)[1]);
}
}
mEmoji = EmojiManager.getAll();
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
InputConnection connection = super.onCreateInputConnection(outAttrs);
int imeActions = outAttrs.imeOptions & EditorInfo.IME_MASK_ACTION;
if ((imeActions & EditorInfo.IME_ACTION_DONE) != 0) {
// clear the existing action
outAttrs.imeOptions ^= imeActions;
// set the DONE action
outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
}
if ((outAttrs.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
}
outAttrs.actionId = EditorInfo.IME_ACTION_DONE;
outAttrs.actionLabel = getContext().getString(R.string.done);
return connection;
}
public static ViewAction forceCommitText(final String text) {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(ContactsCompletionView.class);
}
@Override
public String getDescription() {
return null;
}
@Override
public void perform(UiController uiController, View view) {
ContactsCompletionView completionView = (ContactsCompletionView)view;
InputConnection connection = completionView.testAccessibleInputConnection;
connection.commitText(text, 1);
}
};
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
InputConnection connection = super.onCreateInputConnection(outAttrs);
int imeActions = outAttrs.imeOptions & EditorInfo.IME_MASK_ACTION;
if ((imeActions & EditorInfo.IME_ACTION_DONE) != 0) {
// clear the existing action
outAttrs.imeOptions ^= imeActions;
// set the DONE action
outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
}
if ((outAttrs.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
}
outAttrs.actionId = EditorInfo.IME_ACTION_DONE;
outAttrs.actionLabel = getContext().getString(R.string.done);
return connection;
}
/**
* Commits the chosen word to the text field and saves it for later
* retrieval.
*
* @param suggestion
* the suggestion picked by the user to be committed to the text
* field
* @param correcting
* whether this is due to a correction of an existing word.
*/
private void pickSuggestion(CharSequence suggestion, boolean correcting) {
LatinKeyboardView inputView = mKeyboardSwitcher.getInputView();
int shiftState = getShiftState();
if (shiftState == Keyboard.SHIFT_LOCKED || shiftState == Keyboard.SHIFT_CAPS_LOCKED) {
suggestion = suggestion.toString().toUpperCase(); // all UPPERCASE
}
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
rememberReplacedWord(suggestion);
ic.commitText(suggestion, 1);
}
saveWordInHistory(suggestion);
mPredicting = false;
mCommittedLength = suggestion.length();
((LatinKeyboard) inputView.getKeyboard()).setPreferredLetters(null);
// If we just corrected a word, then don't show punctuations
if (!correcting) {
setNextSuggestions();
}
updateShiftKeyState(getCurrentInputEditorInfo());
}
private boolean isCursorTouchingWord() {
InputConnection ic = getCurrentInputConnection();
if (ic == null)
return false;
CharSequence toLeft = ic.getTextBeforeCursor(1, 0);
CharSequence toRight = ic.getTextAfterCursor(1, 0);
if (!TextUtils.isEmpty(toLeft) && !isWordSeparator(toLeft.charAt(0))
&& !isSuggestedPunctuation(toLeft.charAt(0))) {
return true;
}
if (!TextUtils.isEmpty(toRight) && !isWordSeparator(toRight.charAt(0))
&& !isSuggestedPunctuation(toRight.charAt(0))) {
return true;
}
return false;
}
private void setOldSuggestions() {
if (mCandidateView != null
&& mCandidateView.isShowingAddToDictionaryHint()) {
return;
}
InputConnection ic = getCurrentInputConnection();
if (ic == null)
return;
if (!mPredicting) {
// Extract the selected or touching text
EditingUtil.SelectedWord touching = EditingUtil
.getWordAtCursorOrSelection(ic, mLastSelectionStart,
mLastSelectionEnd, mWordSeparators);
abortCorrection(true);
setNextSuggestions(); // Show the punctuation suggestions list
} else {
abortCorrection(true);
}
}
@Nullable
@Override
public InputConnection onCreateInputConnection(@NonNull EditorInfo outAttrs) {
final InputConnection ic = super.onCreateInputConnection(outAttrs);
if (ic != null && outAttrs.hintText == null) {
// If we don't have a hint and our parent is a TextInputLayout, use its hint for the
// EditorInfo. This allows us to display a hint in 'extract mode'.
outAttrs.hintText = getHintFromLayout();
}
return ic;
}
/**
* This translates incoming hard key events in to edit operations on an
* InputConnection. It is only needed when using the
* PROCESS_HARD_KEYS option.
*/
private boolean translateKeyDown(int keyCode, KeyEvent event) {
mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState,
keyCode, event);
int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(mMetaState));
mMetaState = MetaKeyKeyListener.adjustMetaAfterKeypress(mMetaState);
InputConnection ic = getCurrentInputConnection();
if (c == 0 || ic == null) {
return false;
}
if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
}
if (mComposing.length() > 0) {
char accent = mComposing.charAt(mComposing.length() - 1);
int composed = KeyEvent.getDeadChar(accent, c);
if (composed != 0) {
c = composed;
mComposing.setLength(mComposing.length() - 1);
}
}
onKey(c, null);
return true;
}
public InputConnection onCreateInputConnection(EditorInfo info) {
info.inputType = InputType.TYPE_NULL; // We can't do fancy stuff!
if (con == null) {
con = new CharInputConnection(this, false, inputProcessor);
}
return con;
}
private void removeTrailingSpace() {
final InputConnection ic = getCurrentInputConnection();
if (ic == null)
return;
CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
if (lastOne != null && lastOne.length() == 1
&& lastOne.charAt(0) == ASCII_SPACE) {
ic.deleteSurroundingText(1, 0);
}
}
@Override
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
final InputConnection ic = super.onCreateInputConnection(editorInfo);
if (mimeTypes != null && mCommitContentListener != null && ic != null) {
EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes);
return InputConnectionCompat.createWrapper(ic, editorInfo, (inputContentInfo, flags, opts) -> EditMessage.this.mCommitContentListener.onCommitContent(inputContentInfo, flags, opts, mimeTypes));
} else {
return ic;
}
}
/**
* Cancels the text composition by leaving the already-composed text there
* and clearing the composition state. Use this when the user tries to
* interact with the edit field before composition has finished.
*/
private boolean cancelComposingText() {
InputConnection ic = getCurrentInputConnection();
if (ic == null) {
LogUtils.log(this, Log.WARN, "missing IC %s", ic);
return false;
}
mComposingBraille.clear();
return ic.finishComposingText();
}
@Override
public boolean matchesSafely(View view) {
EditorInfo editorInfo = new EditorInfo();
InputConnection inputConnection = view.onCreateInputConnection(editorInfo);
if (inputConnection == null) {
return false;
}
int actionId =
editorInfo.actionId != 0
? editorInfo.actionId
: editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
return imeActionMatcher.matches(actionId);
}
/**
* 当输入法和EditText建立连接的时候会通过这个方法返回一个InputConnection。
* 我们需要代理这个方法的父类方法生成的InputConnection并返回我们自己的代理类。
* @param outAttrs attrs
* @return
*/
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
//inputConnection = new DeleteInputConnection(super.onCreateInputConnection(outAttrs), true);
inputConnection.setTarget(super.onCreateInputConnection(outAttrs));
return inputConnection;
}
@Override
public void moveCursorRight() {
InputConnection ic = getInputConnection();
if (ic == null) return;
ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT));
ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_RIGHT));
}
/**
* Cache method pointers for performance
*/
private static void initializeMethodsForReflection() {
try {
// These will either both exist or not, so no need for separate try/catch blocks.
// If other methods are added later, use separate try/catch blocks.
sMethodGetSelectedText = InputConnection.class.getMethod("getSelectedText", int.class);
sMethodSetComposingRegion = InputConnection.class.getMethod("setComposingRegion",
int.class, int.class);
} catch (NoSuchMethodException exc) {
// Ignore
}
sMethodsInitialized = true;
}
/**
* Mark text using SHIFT+DPAD
*
* @param con
* input connection
* @param keycode
* DPAD keycode
*/
private void markText(InputConnection con, int keycode) {
long now = SystemClock.uptimeMillis();
con.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0));
con.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0,
KeyEvent.META_SHIFT_LEFT_ON));
con.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0,
KeyEvent.META_SHIFT_LEFT_ON));
con.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0));
}
/**
* Place the cursor on the last occusrance of a symbol
*
* @param con
* driver
* @param symbol
* the symbol to jump to
*/
private void jumpBackward(InputConnection con, int symbol) {
ExtractedText txt = con.getExtractedText(new ExtractedTextRequest(), 0);
if (txt != null) {
int pos = txt.text.toString().lastIndexOf(symbol, txt.selectionEnd - 2);
pos++;
con.setSelection(pos, pos);
}
}
@Override
public void moveCursorLeft() {
InputConnection ic = getInputConnection();
if (ic == null) return;
ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT));
ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_LEFT));
}
private void toUnshifted() {
// Log.d(TAG, "toUnshifted()");
mIsShifted = false;
mComposing.append(UTF7_UNSHIFT);
String decoded = decodeUtf7(mComposing.toString());
InputConnection ic = getCurrentInputConnection();
ic.commitText(decoded, 1);
mComposing = null;
}
private void updateStatus() {
InputConnection ic = getCurrentIC();
if (ic == null) {
return;
}
CharSequence cs = ic.getSelectedText(0);
boolean hasSelection = !TextUtils.isEmpty(cs);
boolean hasClipData = ClipManager.getInstance().hasClipData();
updateSelectAllStatus(hasSelection);
updateCopyStatus(hasSelection);
updatePasteStatus(hasClipData);
updateDeleteStatus(hasSelection || !TextUtils.isEmpty(ic.getTextBeforeCursor(1, 0)));
}
private static boolean requestCursorUpdatesImpl(final InputConnection inputConnection,
final int cursorUpdateMode) {
if (!isRequestCursorUpdatesAvailable()) {
return false;
}
return sRequestCursorUpdatesMethod.invoke(inputConnection, cursorUpdateMode);
}
private int getCursorCapsMode(InputConnection ic, EditorInfo attr) {
int caps = 0;
EditorInfo ei = getCurrentInputEditorInfo();
if (mAutoCapActive && ei != null && ei.inputType != EditorInfo.TYPE_NULL) {
caps = ic.getCursorCapsMode(attr.inputType);
}
return caps;
}
/**
* Removes the word surrounding the cursor. Parameters are identical to
* getWordAtCursor.
*/
public static void deleteWordAtCursor(
InputConnection connection, String separators) {
Range range = getWordRangeAtCursor(connection, separators, null);
if (range == null) return;
connection.finishComposingText();
// Move cursor to beginning of word, to avoid crash when cursor is outside
// of valid range after deleting text.
int newCursor = getCursorPosition(connection) - range.charsBefore;
connection.setSelection(newCursor, newCursor);
connection.deleteSurroundingText(0, range.charsBefore + range.charsAfter);
}
public void onText(CharSequence text) {
// Log.v("SpartacusRex","SOFT : onText "+text.toString());
InputConnection ic = getCurrentInputConnection();
if (ic == null) return;
ic.beginBatchEdit();
if (mComposing.length() > 0) {
commitTyped(ic);
}
ic.commitText(text, 0);
ic.endBatchEdit();
updateShiftKeyState(getCurrentInputEditorInfo());
}