下面列出了怎么用android.view.inputmethod.BaseInputConnection的API类实例代码及写法,或者点击链接到github查看源代码。
public void testRevertAutoCorrectForLanguageWithoutSpaces() {
final String STRING_TO_TYPE = "tgis ";
final String EXPECTED_INTERMEDIATE_RESULT = "this";
final String EXPECTED_FINAL_RESULT = "tgis";
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(STRING_TO_TYPE);
assertEquals("simple auto-correct for language without spaces",
EXPECTED_INTERMEDIATE_RESULT, mEditText.getText().toString());
type(Constants.CODE_DELETE);
assertEquals("simple auto-correct for language without spaces",
EXPECTED_FINAL_RESULT, mEditText.getText().toString());
// Check we are back to composing the word
assertEquals("don't resume suggestion on backspace", 0,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("don't resume suggestion on backspace", 4,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
public void testStartComposingInsideText() {
final String WORD_TO_TYPE = "abcdefgh ";
final int typedLength = WORD_TO_TYPE.length() - 1; // -1 because space gets eaten
final int CURSOR_POS = 4;
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(WORD_TO_TYPE);
mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
mLatinIME.onUpdateSelection(typedLength, typedLength,
CURSOR_POS, CURSOR_POS, -1, -1);
sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
assertEquals("start composing inside text", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("start composing inside text", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
type("xxxx");
assertEquals("start composing inside text", 4,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("start composing inside text", 8,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
public void testViaBackButtonOnView() {
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
sleep();
String url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample3.html"));
BaseInputConnection viewConnection = new BaseInputConnection(testView, true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("index.html"));
}
public void testViaBackButtonOnLayout() {
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
sleep();
String url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample3.html"));
BaseInputConnection viewConnection = new BaseInputConnection(containerView, true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("index.html"));
}
@Override
public InputConnection onCreateInputConnection(EditorInfo editorinfo) {
BaseInputConnection bic = new BaseInputConnection(this, false);
editorinfo.actionLabel = null;
editorinfo.inputType = InputType.TYPE_NULL;
editorinfo.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
bic.finishComposingText();
return bic;
}
/**
* Whether we want to be showing inline autocomplete results. We don't want to show them as the
* user deletes input. Also if there is a composition (e.g. while using the Japanese IME),
* we must not autocomplete or we'll destroy the composition.
* @return Whether we want to be showing inline autocomplete results.
*/
public boolean shouldAutocomplete() {
if (mLastUrlEditWasDelete) return false;
Editable text = getText();
return isCursorAtEndOfTypedText()
&& !isPastedText()
&& !isHandlingBatchInput()
&& BaseInputConnection.getComposingSpanEnd(text)
== BaseInputConnection.getComposingSpanStart(text);
}
private void clean() {
Editable text = mEditor.getText();
BaseInputConnection.removeComposingSpans(text);
/*
Cleanup ParagraphStyles to:
- make sure spans are applied to whole paragraphs
- remove obsolete spans
- Note: the sequence is important
*/
Effects.cleanupParagraphs(mEditor);
}
private void clean() {
Editable text = mEditor.getText();
BaseInputConnection.removeComposingSpans(text);
/*
Cleanup ParagraphStyles to:
- make sure spans are applied to whole paragraphs
- remove obsolete spans
- Note: the sequence is important
*/
Effects.cleanupParagraphs(mEditor);
}
/**
* Whether we want to be showing inline autocomplete results. We don't want to show them as the
* user deletes input. Also if there is a composition (e.g. while using the Japanese IME),
* we must not autocomplete or we'll destroy the composition.
* @return Whether we want to be showing inline autocomplete results.
*/
public boolean shouldAutocomplete() {
if (mLastUrlEditWasDelete) return false;
Editable text = getText();
return isCursorAtEndOfTypedText()
&& !isPastedText()
&& !isHandlingBatchInput()
&& BaseInputConnection.getComposingSpanEnd(text)
== BaseInputConnection.getComposingSpanStart(text);
}
private void clean() {
Editable text = mEditor.getText();
BaseInputConnection.removeComposingSpans(text);
/*
Cleanup ParagraphStyles to:
- make sure spans are applied to whole paragraphs
- remove obsolete spans
- Note: the sequence is important
*/
Effects.cleanupParagraphs(mEditor);
}
/**
* Whether we want to be showing inline autocomplete results. We don't want to show them as the
* user deletes input. Also if there is a composition (e.g. while using the Japanese IME),
* we must not autocomplete or we'll destroy the composition.
* @return Whether we want to be showing inline autocomplete results.
*/
public boolean shouldAutocomplete() {
if (mLastEditWasDelete) return false;
Editable text = getText();
return isCursorAtEndOfTypedText() && !isHandlingBatchInput()
&& BaseInputConnection.getComposingSpanEnd(text)
== BaseInputConnection.getComposingSpanStart(text);
}
/**
* @param editable The editable.
* @return Debug string for the given {@Editable}.
*/
static String getEditableDebugString(Editable editable) {
return String.format(Locale.US, "Editable {[%s] SEL[%d %d] COM[%d %d]}",
editable.toString(), Selection.getSelectionStart(editable),
Selection.getSelectionEnd(editable),
BaseInputConnection.getComposingSpanStart(editable),
BaseInputConnection.getComposingSpanEnd(editable));
}
public void testResumeSuggestionOnBackspace() {
final String STRING_TO_TYPE = "and this ";
final int typedLength = STRING_TO_TYPE.length();
type(STRING_TO_TYPE);
assertEquals("resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
sendUpdateForCursorMoveTo(typedLength);
type(Constants.CODE_DELETE);
assertEquals("resume suggestion on backspace", 4,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("resume suggestion on backspace", 8,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
private void helperTestComposing(final String wordToType, final boolean shouldBeComposing) {
mEditText.setText("");
type(wordToType);
assertEquals("start composing inside text", shouldBeComposing ? 0 : -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("start composing inside text", shouldBeComposing ? wordToType.length() : -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
public void testDontResumeSuggestionOnBackspace() {
final String WORD_TO_TYPE = "and this ";
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(WORD_TO_TYPE);
assertEquals("don't resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("don't resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
type(" ");
type(Constants.CODE_DELETE);
assertEquals("don't resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("don't resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
public void testMovingCursorInsideWordAndType() {
final String WORD_TO_TYPE = "abcdefgh";
final int typedLength = WORD_TO_TYPE.length();
final int CURSOR_POS = 4;
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(WORD_TO_TYPE);
mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, 0, typedLength);
sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
mLatinIME.onUpdateSelection(typedLength, typedLength,
CURSOR_POS, CURSOR_POS, 0, typedLength);
sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
assertEquals("move cursor inside text", 0,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("move cursor inside text", typedLength,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
type("x");
sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
assertEquals("start typing while cursor inside composition", CURSOR_POS,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("start typing while cursor inside composition", CURSOR_POS + 1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new BaseInputConnection(this, false); //this is needed for #dispatchKeyEvent() to be notified.
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new BaseInputConnection(this, false); //this is needed for #dispatchKeyEvent() to be notified.
}
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
Editable currentText = getText();
int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSpan);
if (autoCompleteSpanStart >= 0) {
int composingEnd = BaseInputConnection.getComposingSpanEnd(currentText);
// On certain device/keyboard combinations, the composing regions are specified
// with a noticeable delay after the initial character is typed, and in certain
// circumstances it does not check that the current state of the text matches the
// expectations of it's composing region.
// For example, you can be typing:
// chrome://f
// Chrome will autocomplete to:
// chrome://f[lags]
// And after the autocomplete has been set, the keyboard will set the composing
// region to the last character and it assumes it is 'f' as it was the last
// character the keyboard sent. If we commit this composition, the text will
// look like:
// chrome://flag[f]
// And if we use the autocomplete clearing logic below, it will look like:
// chrome://f[f]
// To work around this, we see if the composition matches all the characters prior
// to the autocomplete and just readjust the composing region to be that subset.
//
// See crbug.com/366732
if (composingEnd == currentText.length()
&& autoCompleteSpanStart >= text.length()
&& TextUtils.equals(
currentText.subSequence(
autoCompleteSpanStart - text.length(),
autoCompleteSpanStart),
text)) {
setComposingRegion(
autoCompleteSpanStart - text.length(), autoCompleteSpanStart);
}
// Once composing text is being modified, the autocomplete text has been accepted
// or has to be deleted.
mAutocompleteSpan.clearSpan();
Selection.setSelection(currentText, autoCompleteSpanStart);
currentText.delete(autoCompleteSpanStart, currentText.length());
}
return super.setComposingText(text, newCursorPosition);
}
@Override
public void afterTextChanged(Editable newText) {
if (formattingCancelled || selfEdit || mask == null || noChanges) {
formattingCancelled = false;
noChanges = false;
return;
}
String formatted = mask.toString();
final int cursorPosition = diffMeasures.getCursorPosition();
// force change text of EditText we're attached to
// only in case it's necessary (formatted text differs from inputted)
if (!formatted.equals(newText.toString())) {
int start = BaseInputConnection.getComposingSpanStart(newText);
int end = cursorPosition > newText.length() ? newText.length() : cursorPosition;
CharSequence pasted;
if (start == -1 || end == -1) {
pasted = formatted;
} else {
SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(formatted.substring(0, start));
SpannableString composing = new SpannableString(formatted.substring(start, end));
// void setComposingSpans(Spannable text, int start, int end) in BaseInputConnection is hide api
BaseInputConnection.setComposingSpans(composing);
sb.append(composing);
sb.append(formatted.substring(end, formatted.length()));
pasted = sb;
}
selfEdit = true;
newText.replace(0, newText.length(), pasted, 0, formatted.length());
selfEdit = false;
}
if (0 <= cursorPosition && cursorPosition <= newText.length()) {
setSelection(cursorPosition);
}
textBeforeChange = null;
if (callback != null) {
callback.onTextFormatted(this, toString());
}
}
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
Editable currentText = getText();
int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSpan);
if (autoCompleteSpanStart >= 0) {
int composingEnd = BaseInputConnection.getComposingSpanEnd(currentText);
// On certain device/keyboard combinations, the composing regions are specified
// with a noticeable delay after the initial character is typed, and in certain
// circumstances it does not check that the current state of the text matches the
// expectations of it's composing region.
// For example, you can be typing:
// chrome://f
// Chrome will autocomplete to:
// chrome://f[lags]
// And after the autocomplete has been set, the keyboard will set the composing
// region to the last character and it assumes it is 'f' as it was the last
// character the keyboard sent. If we commit this composition, the text will
// look like:
// chrome://flag[f]
// And if we use the autocomplete clearing logic below, it will look like:
// chrome://f[f]
// To work around this, we see if the composition matches all the characters prior
// to the autocomplete and just readjust the composing region to be that subset.
//
// See crbug.com/366732
if (composingEnd == currentText.length()
&& autoCompleteSpanStart >= text.length()
&& TextUtils.equals(
currentText.subSequence(
autoCompleteSpanStart - text.length(),
autoCompleteSpanStart),
text)) {
setComposingRegion(
autoCompleteSpanStart - text.length(), autoCompleteSpanStart);
}
// Once composing text is being modified, the autocomplete text has been accepted
// or has to be deleted.
mAutocompleteSpan.clearSpan();
Selection.setSelection(currentText, autoCompleteSpanStart);
currentText.delete(autoCompleteSpanStart, currentText.length());
}
return super.setComposingText(text, newCursorPosition);
}
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
if (DEBUG) Log.i(TAG, "setComposingText: [%s]", text);
Editable currentText = getText();
int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSpan);
if (autoCompleteSpanStart >= 0) {
int composingEnd = BaseInputConnection.getComposingSpanEnd(currentText);
// On certain device/keyboard combinations, the composing regions are specified
// with a noticeable delay after the initial character is typed, and in certain
// circumstances it does not check that the current state of the text matches the
// expectations of it's composing region.
// For example, you can be typing:
// chrome://f
// Chrome will autocomplete to:
// chrome://f[lags]
// And after the autocomplete has been set, the keyboard will set the composing
// region to the last character and it assumes it is 'f' as it was the last
// character the keyboard sent. If we commit this composition, the text will
// look like:
// chrome://flag[f]
// And if we use the autocomplete clearing logic below, it will look like:
// chrome://f[f]
// To work around this, we see if the composition matches all the characters prior
// to the autocomplete and just readjust the composing region to be that subset.
//
// See crbug.com/366732
if (composingEnd == currentText.length() && autoCompleteSpanStart >= text.length()
&& TextUtils.equals(
currentText.subSequence(autoCompleteSpanStart - text.length(),
autoCompleteSpanStart),
text)) {
setComposingRegion(
autoCompleteSpanStart - text.length(), autoCompleteSpanStart);
}
// Once composing text is being modified, the autocomplete text has been accepted
// or has to be deleted.
mAutocompleteSpan.clearSpan();
Selection.setSelection(currentText, autoCompleteSpanStart);
currentText.delete(autoCompleteSpanStart, currentText.length());
}
return super.setComposingText(text, newCursorPosition);
}
private void ensureComposingSpanPos(final String message, final int from, final int to) {
assertEquals(message, from, BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals(message, to, BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}