下面列出了怎么用android.view.inputmethod.ExtractedText的API类实例代码及写法,或者点击链接到github查看源代码。
private void reportExtractedText() {
// custom keyboards don't have an extracted view.
if (mMongolImeManager != null) return;
// TODO cancel this if not in extracted text mode
ExtractedText et = new ExtractedText();
final CharSequence content = getText();
final int length = content.length();
et.partialStartOffset = -1;
et.partialEndOffset = -1;
et.startOffset = 0;
et.selectionStart = getSelectionStart();
et.selectionEnd = getSelectionEnd();
et.flags = 0;
et.text = content.subSequence(0, length);
InputMethodManager imm = (InputMethodManager) getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null) return;
imm.updateExtractedText(this, mExtractedTextRequestToken, et);
}
@Override
public boolean replace(String str1, String str2) {
boolean success = false;
mInputConnection.beginBatchEdit();
ExtractedText extractedText = mInputConnection.getExtractedText(new ExtractedTextRequest(), 0);
if (extractedText != null) {
CharSequence beforeCursor = extractedText.text;
//CharSequence beforeCursor = mInputConnection.getTextBeforeCursor(MAX_SELECTABLE_CONTEXT, 0);
Log.i("replace: " + beforeCursor);
int index = beforeCursor.toString().lastIndexOf(str1);
Log.i("replace: " + index);
if (index > 0) {
mInputConnection.setSelection(index, index);
mInputConnection.deleteSurroundingText(0, str1.length());
if (!str2.isEmpty()) {
mInputConnection.commitText(str2, 0);
}
success = true;
}
mInputConnection.endBatchEdit();
}
return success;
}
@Override
public Op moveAbs(final int pos) {
return new Op("moveAbs " + pos) {
@Override
public Op run() {
Op undo = null;
mInputConnection.beginBatchEdit();
ExtractedText et = getExtractedText();
if (et != null) {
int charPos = pos;
if (pos < 0) {
//-1 == end of text
charPos = et.text.length() + pos + 1;
}
undo = getOpSetSelection(charPos, charPos, et.selectionStart, et.selectionEnd).run();
}
mInputConnection.endBatchEdit();
return undo;
}
};
}
/**
* mInputConnection.performContextMenuAction(android.R.id.selectAll) does not create a selection
*/
@Override
public Op selectAll() {
return new Op("selectAll") {
@Override
public Op run() {
Op undo = null;
mInputConnection.beginBatchEdit();
final ExtractedText et = getExtractedText();
if (et != null) {
undo = getOpSetSelection(0, et.text.length(), et.selectionStart, et.selectionEnd).run();
}
mInputConnection.endBatchEdit();
return undo;
}
};
}
@Override
public Op select(final String query) {
return new Op("select " + query) {
@Override
public Op run() {
Op undo = null;
mInputConnection.beginBatchEdit();
ExtractedText et = getExtractedText();
if (et != null) {
Pair<Integer, CharSequence> queryResult = lastIndexOf(query.replace(F_SELECTION, getSelectedText()), et);
if (queryResult.first >= 0) {
undo = getOpSetSelection(queryResult.first, queryResult.first + queryResult.second.length(), et.selectionStart, et.selectionEnd).run();
}
}
mInputConnection.endBatchEdit();
return undo;
}
};
}
@Override
public Op selectReBefore(final String regex) {
return new Op("selectReBefore") {
@Override
public Op run() {
Op undo = null;
mInputConnection.beginBatchEdit();
final ExtractedText et = getExtractedText();
if (et != null) {
CharSequence input = et.text.subSequence(0, et.selectionStart);
CharSequence selectedText = et.text.subSequence(et.selectionStart, et.selectionEnd);
// 0 == last match
Pair<Integer, Integer> pos = matchNth(Pattern.compile(regex.replace(F_SELECTION, selectedText)), input, 0);
if (pos != null) {
undo = getOpSetSelection(pos.first, pos.second, et.selectionStart, et.selectionEnd).run();
}
}
mInputConnection.endBatchEdit();
return undo;
}
};
}
@Override
public Op selectReAfter(final String regex, final int n) {
return new Op("selectReAfter") {
@Override
public Op run() {
Op undo = null;
mInputConnection.beginBatchEdit();
final ExtractedText et = getExtractedText();
if (et != null) {
CharSequence input = et.text.subSequence(et.selectionEnd, et.text.length());
// TODO: sometimes crashes with:
// StringIndexOutOfBoundsException: String index out of range: -4
CharSequence selectedText = et.text.subSequence(et.selectionStart, et.selectionEnd);
Pair<Integer, Integer> pos = matchNth(Pattern.compile(regex.replace(F_SELECTION, selectedText)), input, n);
if (pos != null) {
undo = getOpSetSelection(et.selectionEnd + pos.first, et.selectionEnd + pos.second, et.selectionStart, et.selectionEnd).run();
}
}
mInputConnection.endBatchEdit();
return undo;
}
};
}
@Override
public Op selectRe(final String regex, final boolean applyToSelection) {
return new Op("selectRe") {
@Override
public Op run() {
Op undo = null;
mInputConnection.beginBatchEdit();
final ExtractedText et = getExtractedText();
if (et != null) {
if (applyToSelection || et.selectionStart == et.selectionEnd) {
Pair<Integer, Integer> pos = matchAtPos(Pattern.compile(regex), et.text, et.selectionStart, et.selectionEnd);
if (pos != null) {
undo = getOpSetSelection(pos.first, pos.second, et.selectionStart, et.selectionEnd).run();
}
}
}
mInputConnection.endBatchEdit();
return undo;
}
};
}
private void updateSelection(TextInputState textInputState) {
if (textInputState == null) return;
assertOnImeThread();
if (mNumNestedBatchEdits != 0) return;
Range selection = textInputState.selection();
Range composition = textInputState.composition();
// As per Guidelines in
// https://developer.android.com/reference/android/view/inputmethod/InputConnection.html
// #getExtractedText(android.view.inputmethod.ExtractedTextRequest,%20int)
// States that if the GET_EXTRACTED_TEXT_MONITOR flag is set,
// you should be calling updateExtractedText(View, int, ExtractedText)
// whenever you call updateSelection(View, int, int, int, int).
if (mShouldUpdateExtractedText) {
final ExtractedText extractedText = convertToExtractedText(textInputState);
mImeAdapter.updateExtractedText(mCurrentExtractedTextRequestToken, extractedText);
}
mImeAdapter.updateSelection(
selection.start(), selection.end(), composition.start(), composition.end());
}
/**
* Try to replace the current word with its substitution.
*/
private void replaceText(InputConnection con) {
ExtractedText txt = con.getExtractedText(new ExtractedTextRequest(), 0);
if (txt != null) {
int end = txt.text.toString().indexOf(" ", txt.selectionEnd);
if (end == -1) {
end = txt.text.length();
}
int start = txt.text.toString().lastIndexOf(" ", txt.selectionEnd - 1);
start++;
String sel = txt.text.subSequence(start, end).toString();
String rep = myService.replacements.get(sel);
if (rep != null) {
con.setComposingRegion(start, end);
con.setComposingText(rep, 1);
con.finishComposingText();
}
else {
String err = myService.getResources().getString(
R.string.err_no_replacement, sel);
Toast.makeText(myService, err, Toast.LENGTH_SHORT).show();
}
}
}
/**
* Implement just to keep track of when we are setting text from the
* client (vs. seeing changes in ourself from the user).
*/
@Override public void setExtractedText(ExtractedText text) {
try {
mSettingExtractedText++;
super.setExtractedText(text);
} finally {
mSettingExtractedText--;
}
}
/**
* Call {@link InputMethodService#onUpdateExtractedText
* InputMethodService.onUpdateExtractedText()}.
*/
public void updateExtractedText(int token, ExtractedText text) {
if (!isEnabled()) {
return;
}
onUpdateExtractedText(token, text);
}
/**
* Called when the application has reported new extracted text to be shown
* due to changes in its current text state. The default implementation
* here places the new text in the extract edit text, when the input
* method is running in fullscreen mode.
*/
public void onUpdateExtractedText(int token, ExtractedText text) {
if (mExtractedToken != token) {
return;
}
if (text != null) {
if (mExtractEditText != null) {
mExtractedText = text;
mExtractEditText.setExtractedText(text);
}
}
}
private void checkConsistencyForDebug() {
final ExtractedTextRequest r = new ExtractedTextRequest();
r.hintMaxChars = 0;
r.hintMaxLines = 0;
r.token = 1;
r.flags = 0;
final ExtractedText et = mIC.getExtractedText(r, 0);
final CharSequence beforeCursor = getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE,
0);
final StringBuilder internal = new StringBuilder(mCommittedTextBeforeComposingText)
.append(mComposingText);
if (null == et || null == beforeCursor) return;
final int actualLength = Math.min(beforeCursor.length(), internal.length());
if (internal.length() > actualLength) {
internal.delete(0, internal.length() - actualLength);
}
final String reference = (beforeCursor.length() <= actualLength) ? beforeCursor.toString()
: beforeCursor.subSequence(beforeCursor.length() - actualLength,
beforeCursor.length()).toString();
if (et.selectionStart != mExpectedSelStart
|| !(reference.equals(internal.toString()))) {
final String context = "Expected selection start = " + mExpectedSelStart
+ "\nActual selection start = " + et.selectionStart
+ "\nExpected text = " + internal.length() + " " + internal
+ "\nActual text = " + reference.length() + " " + reference;
((LatinIME)mParent).debugDumpStateAndCrashWithException(context);
} else {
Log.e(TAG, DebugLogUtils.getStackTrace(2));
Log.e(TAG, "Exp <> Actual : " + mExpectedSelStart + " <> " + et.selectionStart);
}
}
private void checkConsistencyForDebug() {
final ExtractedTextRequest r = new ExtractedTextRequest();
r.hintMaxChars = 0;
r.hintMaxLines = 0;
r.token = 1;
r.flags = 0;
final ExtractedText et = mIC.getExtractedText(r, 0);
final CharSequence beforeCursor = getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE,
0);
final StringBuilder internal = new StringBuilder(mCommittedTextBeforeComposingText)
.append(mComposingText);
if (null == et || null == beforeCursor) return;
final int actualLength = Math.min(beforeCursor.length(), internal.length());
if (internal.length() > actualLength) {
internal.delete(0, internal.length() - actualLength);
}
final String reference = (beforeCursor.length() <= actualLength) ? beforeCursor.toString()
: beforeCursor.subSequence(beforeCursor.length() - actualLength,
beforeCursor.length()).toString();
if (et.selectionStart != mExpectedSelStart
|| !(reference.equals(internal.toString()))) {
final String context = "Expected selection start = " + mExpectedSelStart
+ "\nActual selection start = " + et.selectionStart
+ "\nExpected text = " + internal.length() + " " + internal
+ "\nActual text = " + reference.length() + " " + reference;
((LatinIME)mParent).debugDumpStateAndCrashWithException(context);
} else {
Log.e(TAG, DebugLogUtils.getStackTrace(2));
Log.e(TAG, "Exp <> Actual : " + mExpectedSelStart + " <> " + et.selectionStart);
}
}
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
if (mTextView != null) {
ExtractedText et = new ExtractedText();
if (mTextView.extractText(request, et)) {
if ((flags&GET_EXTRACTED_TEXT_MONITOR) != 0) {
mTextView.setExtracting(request);
}
return et;
}
}
return null;
}
@Override
public void updateExtractedText(@NonNull GeckoSession aSession, @NonNull ExtractedTextRequest request, @NonNull ExtractedText text) {
if (mState.mSession == aSession) {
for (GeckoSession.TextInputDelegate listener : mTextInputListeners) {
listener.updateExtractedText(aSession, request, text);
}
}
}
private String getTextBeforeCursor(InputConnection aConnection) {
if (aConnection == null) {
return "";
}
ExtractedText extracted = aConnection.getExtractedText(new ExtractedTextRequest(),0);
if ((extracted == null) || extracted.text == null) {
return "";
}
String fullText = extracted.text.toString();
return aConnection.getTextBeforeCursor(fullText.length(),0).toString();
}
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
if (request == null)
return null;
Editable editable = getEditable();
if (editable == null) {
return null;
}
int selStart = Selection.getSelectionStart(editable);
int selEnd = Selection.getSelectionEnd(editable);
ExtractedText extract = new ExtractedText();
extract.flags = 0;
extract.partialStartOffset = -1;
extract.partialEndOffset = -1;
extract.selectionStart = selStart;
extract.selectionEnd = selEnd;
extract.startOffset = 0;
if ((request.flags & GET_TEXT_WITH_STYLES) != 0) {
extract.text = new SpannableString(editable);
} else {
extract.text = editable.toString();
}
mMongolEditText.setExtractedTextToken(request.token);
return extract;
}
@Override
public void moveCursorEnd() {
InputConnection ic = getInputConnection();
if (ic == null) return;
ExtractedText extractedText = ic.getExtractedText(new ExtractedTextRequest(), 0);
if (extractedText == null || extractedText.text == null) return;
int length = extractedText.text.length();
ic.setSelection(length, length);
}
@Override
public void selectWordBack() {
InputConnection ic = getInputConnection();
if (ic == null) return;
ExtractedText extractedText = ic.getExtractedText(new ExtractedTextRequest(), 0);
int previousWordBoundary = getPreviousWordBoundary(extractedText.text, extractedText.selectionStart);
int start = extractedText.startOffset + previousWordBoundary;
int end = extractedText.startOffset + extractedText.selectionEnd;
ic.setSelection(start, end);
}
@Override
public void selectWordForward() {
InputConnection ic = getInputConnection();
if (ic == null) return;
ExtractedText extractedText = ic.getExtractedText(new ExtractedTextRequest(), 0);
int nextWordBoundary = getNextWordBoundary(extractedText.text, extractedText.selectionEnd);
int start = extractedText.startOffset + extractedText.selectionStart;
int end = extractedText.startOffset + nextWordBoundary;
ic.setSelection(start, end);
}
private void checkConsistencyForDebug() {
final ExtractedTextRequest r = new ExtractedTextRequest();
r.hintMaxChars = 0;
r.hintMaxLines = 0;
r.token = 1;
r.flags = 0;
final ExtractedText et = mIC.getExtractedText(r, 0);
final CharSequence beforeCursor = getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE,
0);
final StringBuilder internal = new StringBuilder(mCommittedTextBeforeComposingText)
.append(mComposingText);
if (null == et || null == beforeCursor) return;
final int actualLength = Math.min(beforeCursor.length(), internal.length());
if (internal.length() > actualLength) {
internal.delete(0, internal.length() - actualLength);
}
final String reference = (beforeCursor.length() <= actualLength) ? beforeCursor.toString()
: beforeCursor.subSequence(beforeCursor.length() - actualLength,
beforeCursor.length()).toString();
if (et.selectionStart != mExpectedSelStart
|| !(reference.equals(internal.toString()))) {
final String context = "Expected selection start = " + mExpectedSelStart
+ "\nActual selection start = " + et.selectionStart
+ "\nExpected text = " + internal.length() + " " + internal
+ "\nActual text = " + reference.length() + " " + reference;
((LatinIME)mParent).debugDumpStateAndCrashWithException(context);
} else {
Log.e(TAG, DebugLogUtils.getStackTrace(2));
Log.e(TAG, "Exp <> Actual : " + mExpectedSelStart + " <> " + et.selectionStart);
}
}
private void checkConsistencyForDebug() {
final ExtractedTextRequest r = new ExtractedTextRequest();
r.hintMaxChars = 0;
r.hintMaxLines = 0;
r.token = 1;
r.flags = 0;
final ExtractedText et = mIC.getExtractedText(r, 0);
final CharSequence beforeCursor = getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE,
0);
final StringBuilder internal = new StringBuilder(mCommittedTextBeforeComposingText)
.append(mComposingText);
if (null == et || null == beforeCursor) return;
final int actualLength = Math.min(beforeCursor.length(), internal.length());
if (internal.length() > actualLength) {
internal.delete(0, internal.length() - actualLength);
}
final String reference = (beforeCursor.length() <= actualLength) ? beforeCursor.toString()
: beforeCursor.subSequence(beforeCursor.length() - actualLength,
beforeCursor.length()).toString();
if (et.selectionStart != mExpectedSelStart
|| !(reference.equals(internal.toString()))) {
final String context = "Expected selection start = " + mExpectedSelStart
+ "\nActual selection start = " + et.selectionStart
+ "\nExpected text = " + internal.length() + " " + internal
+ "\nActual text = " + reference.length() + " " + reference;
((LatinIME)mParent).debugDumpStateAndCrashWithException(context);
} else {
Log.e(TAG, DebugLogUtils.getStackTrace(2));
Log.e(TAG, "Exp <> Actual : " + mExpectedSelStart + " <> " + et.selectionStart);
}
}
@Override
public void onUpdateExtractedText(int token, ExtractedText text) {
// The superclass only deals with fullscreen support, which we've
// disabled, so don't call it here.
if (mExtractedText == null || token != mExtractedTextToken) {
return;
}
mExtractedText = text;
updateCurrentText();
updateDisplay();
}
private int getCursorPosition() {
ExtractedText extracted = inputConnection.getExtractedText(
new ExtractedTextRequest(), 0);
if (extracted == null) {
return -1;
}
return extracted.startOffset + extracted.selectionStart;
}
@Override
public boolean select(String str) {
boolean success = false;
mInputConnection.beginBatchEdit();
ExtractedText extractedText = mInputConnection.getExtractedText(new ExtractedTextRequest(), 0);
CharSequence beforeCursor = extractedText.text;
int index = beforeCursor.toString().lastIndexOf(str);
if (index > 0) {
mInputConnection.setSelection(index, index + str.length());
success = true;
}
mInputConnection.endBatchEdit();
return success;
}
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
// return ic.getExtractedText(request, flags);
String text = editAreaView.getSelectedText();
if (text == null) text = "";
ExtractedText et = new ExtractedText();
et.text = text;
et.partialEndOffset = text.length();
et.selectionStart = 0;
et.selectionEnd = text.length();
et.flags = 0;
return et;
}
private void checkReCorrectionOnStart() {
if (mReCorrectionEnabled && isPredictionOn()) {
// First get the cursor position. This is required by
// setOldSuggestions(), so that
// it can pass the correct range to setComposingRegion(). At this
// point, we don't
// have valid values for mLastSelectionStart/Stop because
// onUpdateSelection() has
// not been called yet.
InputConnection ic = getCurrentInputConnection();
if (ic == null)
return;
ExtractedTextRequest etr = new ExtractedTextRequest();
etr.token = 0; // anything is fine here
ExtractedText et = ic.getExtractedText(etr, 0);
if (et == null)
return;
mLastSelectionStart = et.startOffset + et.selectionStart;
mLastSelectionEnd = et.startOffset + et.selectionEnd;
// Then look for possible corrections in a delayed fashion
if (!TextUtils.isEmpty(et.text) && isCursorTouchingWord()) {
postUpdateOldSuggestions();
}
}
}
private static int getCursorPosition(InputConnection connection) {
ExtractedText extracted = connection.getExtractedText(
new ExtractedTextRequest(), 0);
if (extracted == null) {
return -1;
}
return extracted.startOffset + extracted.selectionStart;
}