下面列出了android.text.Selection#getSelectionEnd ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* The default implementation uses TextUtils.getCapsMode to get the
* cursor caps mode for the current selection position in the editable
* text, unless in dummy mode in which case 0 is always returned.
*/
public int getCursorCapsMode(int reqModes) {
if (mDummyMode) return 0;
final Editable content = getEditable();
if (content == null) return 0;
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
if (a > b) {
int tmp = a;
a = b;
b = tmp;
}
return TextUtils.getCapsMode(content, a, reqModes);
}
public void run() {
Spannable buf = mBuffer;
if (buf != null) {
int st = Selection.getSelectionStart(buf);
int en = Selection.getSelectionEnd(buf);
int start = buf.getSpanStart(TextKeyListener.ACTIVE);
int end = buf.getSpanEnd(TextKeyListener.ACTIVE);
if (st == start && en == end) {
Selection.setSelection(buf, Selection.getSelectionEnd(buf));
}
buf.removeSpan(Timeout.this);
}
}
/**
* Base implementation handles ACTION_MULTIPLE KEYCODE_UNKNOWN by inserting
* the event's text into the content.
*/
public boolean onKeyOther(View view, Editable content, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_MULTIPLE
|| event.getKeyCode() != KeyEvent.KEYCODE_UNKNOWN) {
// Not something we are interested in.
return false;
}
int selectionStart = Selection.getSelectionStart(content);
int selectionEnd = Selection.getSelectionEnd(content);
if (selectionEnd < selectionStart) {
int temp = selectionEnd;
selectionEnd = selectionStart;
selectionStart = temp;
}
CharSequence text = event.getCharacters();
if (text == null) {
return false;
}
content.replace(selectionStart, selectionEnd, text);
return true;
}
public void onBeforeNotifyDataSetChanged() {
if (SUPPORTED) {
HANDLER.removeMessages(MESSAGE_SEND_RESET);
HANDLER.removeMessages(MESSAGE_RESET);
HANDLER.removeMessages(MESSAGE_START_SELECTION);
if (selectionActionMode != null) {
final CharSequence text = selectionTextView.getText();
futureSelectionIdentifier = selectionIdentifier;
futureSelectionStart = Selection.getSelectionStart(text);
futureSelectionEnd = Selection.getSelectionEnd(text);
selectionActionMode.finish();
selectionActionMode = null;
selectionIdentifier = null;
selectionTextView = null;
}
}
}
/**
* The default implementation returns the given amount of text from the
* current cursor position in the buffer.
*/
public CharSequence getTextBeforeCursor(int length, int flags) {
final Editable content = getEditable();
if (content == null) return null;
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
if (a > b) {
int tmp = a;
a = b;
b = tmp;
}
if (a <= 0) {
return "";
}
if (length > a) {
length = a;
}
if ((flags&GET_TEXT_WITH_STYLES) != 0) {
return content.subSequence(a - length, a);
}
return TextUtils.substring(content, a - length, a);
}
/**
* @see BaseInputConnection#getExtractedText(android.view.inputmethod.ExtractedTextRequest,
* int)
*/
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
if (DEBUG) Log.w(TAG, "getExtractedText");
ExtractedText et = new ExtractedText();
Editable editable = getEditable();
et.text = editable.toString();
et.partialEndOffset = editable.length();
et.selectionStart = Selection.getSelectionStart(editable);
et.selectionEnd = Selection.getSelectionEnd(editable);
et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0;
return et;
}
/**
* @see BaseInputConnection#deleteSurroundingText(int, int)
*/
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
if (DEBUG) {
Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLength + "]");
}
Editable editable = getEditable();
int availableBefore = Selection.getSelectionStart(editable);
int availableAfter = editable.length() - Selection.getSelectionEnd(editable);
beforeLength = Math.min(beforeLength, availableBefore);
afterLength = Math.min(afterLength, availableAfter);
super.deleteSurroundingText(beforeLength, afterLength);
updateSelectionIfRequired();
return mImeAdapter.deleteSurroundingText(beforeLength, afterLength);
}
/**
* @see BaseInputConnection#deleteSurroundingText(int, int)
*/
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
if (DEBUG) {
Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLength + "]");
}
Editable editable = getEditable();
int availableBefore = Selection.getSelectionStart(editable);
int availableAfter = editable.length() - Selection.getSelectionEnd(editable);
beforeLength = Math.min(beforeLength, availableBefore);
afterLength = Math.min(afterLength, availableAfter);
super.deleteSurroundingText(beforeLength, afterLength);
updateSelectionIfRequired();
return mImeAdapter.deleteSurroundingText(beforeLength, afterLength);
}
/**
* Sends selection update to the InputMethodManager unless we are currently in a batch edit or
* if the exact same selection and composition update was sent already.
*/
private void updateSelectionIfRequired() {
if (mNumNestedBatchEdits != 0) return;
Editable editable = getEditable();
int selectionStart = Selection.getSelectionStart(editable);
int selectionEnd = Selection.getSelectionEnd(editable);
int compositionStart = getComposingSpanStart(editable);
int compositionEnd = getComposingSpanEnd(editable);
// Avoid sending update if we sent an exact update already previously.
if (mLastUpdateSelectionStart == selectionStart &&
mLastUpdateSelectionEnd == selectionEnd &&
mLastUpdateCompositionStart == compositionStart &&
mLastUpdateCompositionEnd == compositionEnd) {
return;
}
if (DEBUG) {
Log.w(TAG, "updateSelectionIfRequired [" + selectionStart + " " + selectionEnd + "] ["
+ compositionStart + " " + compositionEnd + "]");
}
// updateSelection should be called every time the selection or composition changes
// if it happens not within a batch edit, or at the end of each top level batch edit.
getInputMethodManagerWrapper().updateSelection(mInternalView,
selectionStart, selectionEnd, compositionStart, compositionEnd);
mLastUpdateSelectionStart = selectionStart;
mLastUpdateSelectionEnd = selectionEnd;
mLastUpdateCompositionStart = compositionStart;
mLastUpdateCompositionEnd = compositionEnd;
}
/**
* @see BaseInputConnection#getExtractedText(android.view.inputmethod.ExtractedTextRequest,
* int)
*/
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
if (DEBUG) Log.w(TAG, "getExtractedText");
ExtractedText et = new ExtractedText();
Editable editable = getEditable();
et.text = editable.toString();
et.partialEndOffset = editable.length();
et.selectionStart = Selection.getSelectionStart(editable);
et.selectionEnd = Selection.getSelectionEnd(editable);
et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0;
return et;
}
/**
* Performs the action that happens when you press the DEL key in
* a TextView. If there is a selection, deletes the selection;
* otherwise, DEL alone deletes the character before the cursor,
* if any;
* ALT+DEL deletes everything on the line the cursor is on.
*
* @return true if anything was deleted; false otherwise.
*/
public boolean forwardDelete(View view, Editable content, int keyCode,
KeyEvent event) {
int selStart, selEnd;
boolean result = true;
{
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
selStart = Math.min(a, b);
selEnd = Math.max(a, b);
}
if (selStart != selEnd) {
content.delete(selStart, selEnd);
} else {
int to = TextUtils.getOffsetAfter(content, selEnd);
if (to != selEnd) {
content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
}
else {
result = false;
}
}
if (result)
adjustMetaAfterKeypress(content);
return result;
}
/**
* Performs the action that happens when you press the DEL key in
* a TextView. If there is a selection, deletes the selection;
* otherwise, DEL alone deletes the character before the cursor,
* if any;
* ALT+DEL deletes everything on the line the cursor is on.
*
* @return true if anything was deleted; false otherwise.
*/
public boolean forwardDelete(View view, Editable content, int keyCode,
KeyEvent event) {
int selStart, selEnd;
boolean result = true;
{
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
selStart = Math.min(a, b);
selEnd = Math.max(a, b);
}
if (selStart != selEnd) {
content.delete(selStart, selEnd);
} else {
int to = TextUtils.getOffsetAfter(content, selEnd);
if (to != selEnd) {
content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
}
else {
result = false;
}
}
if (result)
adjustMetaAfterKeypress(content);
return result;
}
/**
* Sends selection update to the InputMethodManager unless we are currently in a batch edit or
* if the exact same selection and composition update was sent already.
*/
private void updateSelectionIfRequired() {
if (mNumNestedBatchEdits != 0) return;
Editable editable = getEditable();
int selectionStart = Selection.getSelectionStart(editable);
int selectionEnd = Selection.getSelectionEnd(editable);
int compositionStart = getComposingSpanStart(editable);
int compositionEnd = getComposingSpanEnd(editable);
// Avoid sending update if we sent an exact update already previously.
if (mLastUpdateSelectionStart == selectionStart &&
mLastUpdateSelectionEnd == selectionEnd &&
mLastUpdateCompositionStart == compositionStart &&
mLastUpdateCompositionEnd == compositionEnd) {
return;
}
if (DEBUG) {
Log.w(TAG, "updateSelectionIfRequired [" + selectionStart + " " + selectionEnd + "] ["
+ compositionStart + " " + compositionEnd + "]");
}
// updateSelection should be called every time the selection or composition changes
// if it happens not within a batch edit, or at the end of each top level batch edit.
getInputMethodManagerWrapper().updateSelection(mInternalView,
selectionStart, selectionEnd, compositionStart, compositionEnd);
mLastUpdateSelectionStart = selectionStart;
mLastUpdateSelectionEnd = selectionEnd;
mLastUpdateCompositionStart = compositionStart;
mLastUpdateCompositionEnd = compositionEnd;
}
@VisibleForTesting
ImeState getImeStateForTesting() {
Editable editable = getEditable();
String text = editable.toString();
int selectionStart = Selection.getSelectionStart(editable);
int selectionEnd = Selection.getSelectionEnd(editable);
int compositionStart = getComposingSpanStart(editable);
int compositionEnd = getComposingSpanEnd(editable);
return new ImeState(text, selectionStart, selectionEnd, compositionStart, compositionEnd);
}
private void formatTextWhenDelete(final Editable editable, int start, int before) {
mIsFormatted = true;
final boolean filter = mFilterRestoreTextChangeEvent;
super.removeTextChangedListener(mTextWatcher);
InputFilter[] filters = editable.getFilters();
editable.setFilters(EMPTY_FILTERS);
int selectionStart, selectionEnd;
if (!filter) {
selectionStart = Selection.getSelectionStart(editable);
selectionEnd = Selection.getSelectionEnd(editable);
editable.setSpan(SELECTION_SPAN, selectionStart, selectionEnd, Spanned.SPAN_MARK_MARK);
}
if (mMode < MODE_MASK) {
final boolean deletedLast = start >= editable.length();
if (!deletedLast) {
formatDefined(editable, start, true);
} else {
for (int i = start; i > 0; i--) {
final char sub = editable.charAt(i - 1);
final char place = findPlaceholder(i - 1);
if (sub == place) {
editable.delete(i - 1, i);
} else {
break;
}
}
}
} else {
formatMask(editable, start, true);
}
if (!filter) {
selectionStart = editable.getSpanStart(SELECTION_SPAN);
selectionEnd = editable.getSpanEnd(SELECTION_SPAN);
editable.removeSpan(SELECTION_SPAN);
editable.setFilters(filters);
Editable text = getText();
Selection.setSelection(text, selectionStart, selectionEnd);
} else {
setFilters(filters);
}
mIsFormatted = false;
super.addTextChangedListener(mTextWatcher);
}
/**
* @see BaseInputConnection#sendKeyEvent(android.view.KeyEvent)
*/
@Override
public boolean sendKeyEvent(KeyEvent event) {
if (DEBUG) {
Log.w(TAG, "sendKeyEvent [" + event.getAction() + "] [" + event.getKeyCode() + "]");
}
// If this is a key-up, and backspace/del or if the key has a character representation,
// need to update the underlying Editable (i.e. the local representation of the text
// being edited).
if (event.getAction() == KeyEvent.ACTION_UP) {
if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
deleteSurroundingText(1, 0);
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) {
deleteSurroundingText(0, 1);
return true;
} else {
int unicodeChar = event.getUnicodeChar();
if (unicodeChar != 0) {
Editable editable = getEditable();
int selectionStart = Selection.getSelectionStart(editable);
int selectionEnd = Selection.getSelectionEnd(editable);
if (selectionStart > selectionEnd) {
int temp = selectionStart;
selectionStart = selectionEnd;
selectionEnd = temp;
}
editable.replace(selectionStart, selectionEnd,
Character.toString((char)unicodeChar));
}
}
} else if (event.getAction() == KeyEvent.ACTION_DOWN) {
// TODO(aurimas): remove this workaround when crbug.com/278584 is fixed.
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
beginBatchEdit();
finishComposingText();
mImeAdapter.translateAndSendNativeEvents(event);
endBatchEdit();
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) {
return true;
}
}
mImeAdapter.translateAndSendNativeEvents(event);
return true;
}
@Override
public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) {
boolean result = super.onKeyDown(view, content, keyCode, event);
// auto indent
if ( sAutoIndent && keyCode == KeyEvent.KEYCODE_ENTER ){
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
if ( a == b ){
// search head of previous line
int prev = a-2;
while( prev >=0 && content.charAt(prev)!='\n' ){
prev--;
}
prev ++;
int pos = prev;
while( content.charAt(pos)==' ' || content.charAt(pos)=='\t' || content.charAt(pos)=='\u3000'){
pos++;
}
int len = pos-prev;
if ( len > 0 ){
char [] dest = new char[len];
content.getChars(prev, pos, dest, 0);
content.replace(a,b, new String(dest) );
Selection.setSelection(content, a+len);
}
}
}
if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ){
if (keyCode == KEYCODE_FORWARD_DEL ) {
if ( (event.getMetaState() & 512) == 0 ){ // workaround for Galaxy Note
forwardDelete(view, content, keyCode, event);
return true;
}
}
}
return result;
}
private boolean deleteUntilWordBoundary(View view, Editable content, boolean isForwardDelete) {
int currentCursorOffset = Selection.getSelectionStart(content);
// If there is a selection, do nothing.
if (currentCursorOffset != Selection.getSelectionEnd(content)) {
return false;
}
// Early exit if there is no contents to delete.
if ((!isForwardDelete && currentCursorOffset == 0) ||
(isForwardDelete && currentCursorOffset == content.length())) {
return false;
}
WordIterator wordIterator = null;
if (view instanceof TextView) {
wordIterator = ((TextView)view).getWordIterator();
}
if (wordIterator == null) {
// Default locale is used for WordIterator since the appropriate locale is not clear
// here.
// TODO: Use appropriate locale for WordIterator.
wordIterator = new WordIterator();
}
int deleteFrom;
int deleteTo;
if (isForwardDelete) {
deleteFrom = currentCursorOffset;
wordIterator.setCharSequence(content, deleteFrom, content.length());
deleteTo = wordIterator.following(currentCursorOffset);
if (deleteTo == BreakIterator.DONE) {
deleteTo = content.length();
}
} else {
deleteTo = currentCursorOffset;
wordIterator.setCharSequence(content, 0, deleteTo);
deleteFrom = wordIterator.preceding(currentCursorOffset);
if (deleteFrom == BreakIterator.DONE) {
deleteFrom = 0;
}
}
content.delete(deleteFrom, deleteTo);
return true;
}
private boolean action(int what, TextView widget, Spannable buffer) {
Layout layout = widget.getLayout();
int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
int areatop = widget.getScrollY();
int areabot = areatop + widget.getHeight() - padding;
int linetop = layout.getLineForVertical(areatop);
int linebot = layout.getLineForVertical(areabot);
int first = layout.getLineStart(linetop);
int last = layout.getLineEnd(linebot);
MyURLSpan[] candidates = buffer.getSpans(first, last, MyURLSpan.class);
int a = Selection.getSelectionStart(buffer);
int b = Selection.getSelectionEnd(buffer);
int selStart = Math.min(a, b);
int selEnd = Math.max(a, b);
if (selStart < 0) {
if (buffer.getSpanStart(FROM_BELOW) >= 0) {
selStart = selEnd = buffer.length();
}
}
if (selStart > last) {
selStart = selEnd = Integer.MAX_VALUE;
}
if (selEnd < first) {
selStart = selEnd = -1;
}
switch (what) {
case CLICK:
if (selStart == selEnd) {
return false;
}
MyURLSpan[] link = buffer.getSpans(selStart, selEnd, MyURLSpan.class);
if (link.length != 1) {
return false;
}
link[0].onClick(widget);
break;
case UP:
int best_start = -1;
int best_end = -1;
for (MyURLSpan candidate1 : candidates) {
int end = buffer.getSpanEnd(candidate1);
if (end < selEnd || selStart == selEnd) {
if (end > best_end) {
best_start = buffer.getSpanStart(candidate1);
best_end = end;
}
}
}
if (best_start >= 0) {
Selection.setSelection(buffer, best_end, best_start);
return true;
}
break;
case DOWN:
best_start = Integer.MAX_VALUE;
best_end = Integer.MAX_VALUE;
for (MyURLSpan candidate : candidates) {
int start = buffer.getSpanStart(candidate);
if (start > selStart || selStart == selEnd) {
if (start < best_start) {
best_start = start;
best_end = buffer.getSpanEnd(candidate);
}
}
}
if (best_end < Integer.MAX_VALUE) {
Selection.setSelection(buffer, best_start, best_end);
return true;
}
break;
}
return false;
}
private boolean action(int what, TextView widget, Spannable buffer) {
Layout layout = widget.getLayout();
int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
int areatop = widget.getScrollY();
int areabot = areatop + widget.getHeight() - padding;
int linetop = layout.getLineForVertical(areatop);
int linebot = layout.getLineForVertical(areabot);
int first = layout.getLineStart(linetop);
int last = layout.getLineEnd(linebot);
ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class);
int a = Selection.getSelectionStart(buffer);
int b = Selection.getSelectionEnd(buffer);
int selStart = Math.min(a, b);
int selEnd = Math.max(a, b);
if (selStart < 0) {
if (buffer.getSpanStart(FROM_BELOW) >= 0) {
selStart = selEnd = buffer.length();
}
}
if (selStart > last) selStart = selEnd = Integer.MAX_VALUE;
if (selEnd < first) selStart = selEnd = -1;
switch (what) {
case CLICK:
if (selStart == selEnd) {
return false;
}
ClickableSpan[] link = buffer.getSpans(selStart, selEnd, ClickableSpan.class);
if (link.length != 1) return false;
link[0].onClick(widget);
break;
case UP:
int beststart, bestend;
beststart = -1;
bestend = -1;
for (int i = 0; i < candidates.length; i++) {
int end = buffer.getSpanEnd(candidates[i]);
if (end < selEnd || selStart == selEnd) {
if (end > bestend) {
beststart = buffer.getSpanStart(candidates[i]);
bestend = end;
}
}
}
if (beststart >= 0) {
Selection.setSelection(buffer, bestend, beststart);
return true;
}
break;
case DOWN:
beststart = Integer.MAX_VALUE;
bestend = Integer.MAX_VALUE;
for (int i = 0; i < candidates.length; i++) {
int start = buffer.getSpanStart(candidates[i]);
if (start > selStart || selStart == selEnd) {
if (start < beststart) {
beststart = start;
bestend = buffer.getSpanEnd(candidates[i]);
}
}
}
if (bestend < Integer.MAX_VALUE) {
Selection.setSelection(buffer, beststart, bestend);
return true;
}
break;
}
return false;
}