下面列出了android.text.Layout#getLineForVertical ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private TouchableSpan getPressedSpan(TextView textView, Spannable spannable, MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= textView.getTotalPaddingLeft();
y -= textView.getTotalPaddingTop();
x += textView.getScrollX();
y += textView.getScrollY();
Layout layout = textView.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
TouchableSpan[] link = spannable.getSpans(off, off, TouchableSpan.class);
TouchableSpan touchedSpan = null;
if (link.length > 0) {
touchedSpan = link[0];
}
return touchedSpan;
}
/**
* Performs a scroll down action.
* Scrolls down by the specified number of lines.
*
* @param widget The text view.
* @param buffer The text buffer.
* @param amount The number of lines to scroll by. Must be at least 1.
* @return True if the event was handled.
* @hide
*/
protected boolean scrollDown(TextView widget, Spannable buffer, int amount) {
final Layout layout = widget.getLayout();
final int innerHeight = getInnerHeight(widget);
final int bottom = widget.getScrollY() + innerHeight;
int bottomLine = layout.getLineForVertical(bottom);
if (layout.getLineTop(bottomLine + 1) < bottom + 1) {
// Less than a pixel of this line is out of view,
// so we must have tried to make it entirely in view
// and now want the next line to be in view instead.
bottomLine += 1;
}
final int limit = layout.getLineCount() - 1;
if (bottomLine <= limit) {
bottomLine = Math.min(bottomLine + amount - 1, limit);
Touch.scrollTo(widget, layout, widget.getScrollX(),
layout.getLineTop(bottomLine + 1) - innerHeight);
return true;
}
return false;
}
public static boolean handleClickableSpan(View view, Layout layout, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= view.getPaddingLeft();
y -= view.getPaddingTop();
x += view.getScrollX();
y += view.getScrollY();
int line = layout.getLineForVertical(y);
line = Math.min(layout.getLineCount() - 1, line); // 避免line超出line count
int off = getOffsetForHorizontal(view, layout, x, line);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(view);
} else {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return false;
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length > 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else {
Selection.setSelection(buffer, buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return false;
}
private int getOffsetForHorizontal(TextView widget,
MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
return layout.getOffsetForHorizontal(line, x);
}
/**
* Performs a scroll page up action.
* Scrolls up by one page.
*
* @param widget The text view.
* @param buffer The text buffer.
* @return True if the event was handled.
* @hide
*/
protected boolean scrollPageUp(TextView widget, Spannable buffer) {
final Layout layout = widget.getLayout();
final int top = widget.getScrollY() - getInnerHeight(widget);
int topLine = layout.getLineForVertical(top);
if (topLine >= 0) {
Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine));
return true;
}
return false;
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length > 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else {
Selection.setSelection(buffer, buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return false;
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
// Let the parent or grandparent of TextView to handles click aciton.
// Otherwise click effect like ripple will not work, and if touch area
// do not contain a url, the TextView will still get MotionEvent.
// onTouchEven must be called with MotionEvent.ACTION_DOWN for each touch
// action on it, so we analyze touched url here.
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mCurrentSpan = null;
if (getText() instanceof Spanned) {
// Get this code from android.text.method.LinkMovementMethod.
// Work fine !
int x = (int) event.getX();
int y = (int) event.getY();
x -= getTotalPaddingLeft();
y -= getTotalPaddingTop();
x += getScrollX();
y += getScrollY();
Layout layout = getLayout();
if (null != layout) {
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] spans = ((Spanned)getText()).getSpans(off, off, ClickableSpan.class);
if (spans.length > 0) {
mCurrentSpan = spans[0];
}
}
}
}
return super.onTouchEvent(event);
}
@Override
public boolean onTouchEvent(TextView widget,
Spannable buffer, MotionEvent event ) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP)
{
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
if (link.length != 0)
{
// display the license
displayLicense();
return true;
}
}
return super.onTouchEvent(widget, buffer, event);
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]));
}
return true;
}
/*else {
that's the line we need to remove
Selection.removeSelection(buffer);
}*/
}
return super.onTouchEvent(widget, buffer, event);
}
/**
* Gets the {@link MentionSpan} from the {@link MentionsEditText} that was tapped.
* <p>
* Note: Almost all of this code is taken directly from the Android source code, see:
* {@link LinkMovementMethod#onTouchEvent(TextView, Spannable, MotionEvent)}
*
* @param event the given (@link MotionEvent}
*
* @return the tapped {@link MentionSpan}, or null if one was not tapped
*/
@Nullable
protected MentionSpan getTouchedSpan(@NonNull MotionEvent event) {
Layout layout = getLayout();
// Note: Layout can be null if text or width has recently changed, see MOB-38193
if (event == null || layout == null) {
return null;
}
int x = (int) event.getX();
int y = (int) event.getY();
x -= getTotalPaddingLeft();
y -= getTotalPaddingTop();
x += getScrollX();
y += getScrollY();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
Editable text = getText();
if (text != null && off >= getText().length()) {
return null;
}
// Get the MentionSpans in the area that the user tapped
// If one exists, call the onClick method manually
MentionSpan[] spans = getText().getSpans(off, off, MentionSpan.class);
if (spans.length > 0) {
return spans[0];
}
return null;
}
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 (ClickableSpan candidate1 : candidates) {
int end = buffer.getSpanEnd(candidate1);
if (end < selEnd || selStart == selEnd) {
if (end > bestend) {
beststart = buffer.getSpanStart(candidate1);
bestend = end;
}
}
}
if (beststart >= 0) {
Selection.setSelection(buffer, bestend, beststart);
return true;
}
break;
case DOWN:
beststart = Integer.MAX_VALUE;
bestend = Integer.MAX_VALUE;
for (ClickableSpan candidate : candidates) {
int start = buffer.getSpanStart(candidate);
if (start > selStart || selStart == selEnd) {
if (start < beststart) {
beststart = start;
bestend = buffer.getSpanEnd(candidate);
}
}
}
if (bestend < Integer.MAX_VALUE) {
Selection.setSelection(buffer, beststart, bestend);
return true;
}
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Object text = this.getText();
if (text instanceof Spanned) {
Spannable buffer = Spannable.Factory.getInstance().newSpannable((CharSequence) text);
int action = event.getAction();
if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= this.getTotalPaddingLeft();
y -= this.getTotalPaddingTop();
x += this.getScrollX();
y += this.getScrollY();
Layout layout = this.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(this);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(
buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0])
);
}
return true;
}
}
}
return false;
}
/**
* Scrolls the specified widget to the specified coordinates, except
* constrains the X scrolling position to the horizontal regions of
* the text that will be visible after scrolling to the specified
* Y position.
*/
public static void scrollTo(TextView widget, Layout layout, int x, int y) {
final int horizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
final int availableWidth = widget.getWidth() - horizontalPadding;
final int top = layout.getLineForVertical(y);
Alignment a = layout.getParagraphAlignment(top);
boolean ltr = layout.getParagraphDirection(top) > 0;
int left, right;
if (widget.getHorizontallyScrolling()) {
final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding);
left = Integer.MAX_VALUE;
right = 0;
for (int i = top; i <= bottom; i++) {
left = (int) Math.min(left, layout.getLineLeft(i));
right = (int) Math.max(right, layout.getLineRight(i));
}
} else {
left = 0;
right = availableWidth;
}
final int actualWidth = right - left;
if (actualWidth < availableWidth) {
if (a == Alignment.ALIGN_CENTER) {
x = left - ((availableWidth - actualWidth) / 2);
} else if ((ltr && (a == Alignment.ALIGN_OPPOSITE)) ||
(!ltr && (a == Alignment.ALIGN_NORMAL)) ||
(a == Alignment.ALIGN_RIGHT)) {
// align_opposite does NOT mean align_right, we need the paragraph
// direction to resolve it to left or right
x = left - (availableWidth - actualWidth);
} else {
x = left;
}
} else {
x = Math.min(x, right - availableWidth);
x = Math.max(x, left);
}
widget.scrollTo(x, y);
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
onLinkClick(link[0]);
// URLSpan[] linkUrlSpan = buffer.getSpans(off, off, URLSpan.class);
// if (linkUrlSpan[0].getURL().toString().startsWith(urlStartWith)) {
//onLinkClick(linkUrlSpan[0].getURL());
// }else {
// link[0].onClick(widget);
// }
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return super.onTouchEvent(widget, buffer, event);
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
try {
link[0].onClick(widget);
} catch (Exception e) {
e.printStackTrace();
ToastUtil.e(R.string.not_foud_qq);
}
if (((URLSpan) link[0]).getURL() != null) {
if (DonateActivity.zhifubao.startsWith(((URLSpan) link[0]).getURL())) {
UrlCountUtil.onEvent(UrlCountUtil.CLICK_SETTINGS_ABOUT_DONATE);
} else if (DonateActivity.qqJump.startsWith(((URLSpan) link[0]).getURL())) {
UrlCountUtil.onEvent(UrlCountUtil.CLICK_SETTINGS_JOIN_QQ);
}
}
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return super.onTouchEvent(widget, buffer, event);
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_DOWN
|| action == MotionEvent.ACTION_MOVE
|| action == MotionEvent.ACTION_CANCEL) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] clickableLinks = buffer.getSpans(off, off, ClickableSpan.class);
LongPressClickableSpan[] longPressClickableLinks = buffer.getSpans(off, off, LongPressClickableSpan.class);
switch (action) {
case MotionEvent.ACTION_UP:
if (clickableLinks.length != 0) {
if (!mIsLongPressed) {
clickableLinks[0].onClick(widget);
}
mIsLongPressed = false;
mHandler.removeMessages(LONG_PRESS);
}
return true;
case MotionEvent.ACTION_DOWN:
if (clickableLinks.length != 0) {
if (longPressClickableLinks.length == 0) {
Selection.setSelection(buffer,
buffer.getSpanStart(clickableLinks[0]),
buffer.getSpanEnd(clickableLinks[0]));
} else {
mX = (int) event.getX();
mY = (int) event.getY();
mHandler.removeMessages(LONG_PRESS);
mHandler.sendMessageAtTime(Message.obtain(mHandler, LONG_PRESS, new Object[]{longPressClickableLinks[0], widget}),
event.getDownTime() + ViewConfiguration.getLongPressTimeout());
}
}
return true;
case MotionEvent.ACTION_MOVE:
if (Math.abs(event.getX() - mX) > 50
&& Math.abs(event.getX() - mY) > 50) {
mHandler.removeMessages(LONG_PRESS);
}
return super.onTouchEvent(widget, buffer, event);
case MotionEvent.ACTION_CANCEL:
mHandler.removeMessages(LONG_PRESS);
return super.onTouchEvent(widget, buffer, event);
}
if (clickableLinks.length == 0) {
Selection.removeSelection(buffer);
}
}
return super.onTouchEvent(widget, buffer, event);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (!(v instanceof TextView)) {
return false;
}
TextView widget = (TextView) v;
//widget.getText() is SpannedString
Spannable buffer = Spannable.Factory.getInstance().newSpannable(widget.getText());
int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);
if (links.length != 0) {
if (action == MotionEvent.ACTION_UP) {
removeLongClick(v);
links[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer, buffer.getSpanStart(links[0]), buffer.getSpanEnd(links[0]));
checkForLongClick(v, 0);
}
return true;
} else {
Selection.removeSelection(buffer);
}
} else if (action == MotionEvent.ACTION_CANCEL) {
removeLongClick(v);
}
return false;
}
@Override
public int reactTagForTouch(float touchX, float touchY) {
CharSequence text = getText();
int target = getId();
int x = (int) touchX;
int y = (int) touchY;
Layout layout = getLayout();
if (layout == null) {
// If the layout is null, the view hasn't been properly laid out yet. Therefore, we can't find
// the exact text tag that has been touched, and the correct tag to return is the default one.
return target;
}
int line = layout.getLineForVertical(y);
int lineStartX = (int) layout.getLineLeft(line);
int lineEndX = (int) layout.getLineRight(line);
// TODO(5966918): Consider extending touchable area for text spans by some DP constant
if (text instanceof Spanned && x >= lineStartX && x <= lineEndX) {
Spanned spannedText = (Spanned) text;
int index = layout.getOffsetForHorizontal(line, x);
// We choose the most inner span (shortest) containing character at the given index
// if no such span can be found we will send the textview's react id as a touch handler
// In case when there are more than one spans with same length we choose the last one
// from the spans[] array, since it correspond to the most inner react element
ReactTagSpan[] spans = spannedText.getSpans(index, index, ReactTagSpan.class);
if (spans != null) {
int targetSpanTextLength = text.length();
for (int i = 0; i < spans.length; i++) {
int spanStart = spannedText.getSpanStart(spans[i]);
int spanEnd = spannedText.getSpanEnd(spans[i]);
if (spanEnd > index && (spanEnd - spanStart) <= targetSpanTextLength) {
target = spans[i].getReactTag();
targetSpanTextLength = (spanEnd - spanStart);
}
}
}
}
return target;
}
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;
}