Java Code Examples for android.text.Layout#getLineForVertical()
The following examples show how to use
android.text.Layout#getLineForVertical() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: LinkTextView.java From LinkTextView with MIT License | 6 votes |
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; }
Example 2
Source File: BaseMovementMethod.java From android_9.0.0_r45 with Apache License 2.0 | 6 votes |
/** * 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; }
Example 3
Source File: ClickLinkMovementMethod.java From xifan with Apache License 2.0 | 5 votes |
@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; }
Example 4
Source File: NameTouchMovementMethod.java From meiShi with Apache License 2.0 | 5 votes |
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); }
Example 5
Source File: MentionsEditText.java From Spyglass with Apache License 2.0 | 5 votes |
/** * 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; }
Example 6
Source File: BaseMovementMethod.java From android_9.0.0_r45 with Apache License 2.0 | 5 votes |
/** * 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; }
Example 7
Source File: ClickableMovementMethod.java From qiscus-sdk-android with Apache License 2.0 | 5 votes |
@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; }
Example 8
Source File: ClickableSpanUtil.java From FastTextView with Apache License 2.0 | 5 votes |
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; }
Example 9
Source File: SelectableLinkMovementMethod.java From mimi-reader with Apache License 2.0 | 5 votes |
@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); }
Example 10
Source File: LinkifyTextView.java From MHViewer with Apache License 2.0 | 5 votes |
@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); }
Example 11
Source File: HomeActivity.java From matrix-android-console with Apache License 2.0 | 5 votes |
@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); }
Example 12
Source File: TextViewLinkHandler.java From chat21-android-sdk with GNU Affero General Public License v3.0 | 4 votes |
@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); }
Example 13
Source File: CountLinkMovementMethod.java From timecat with Apache License 2.0 | 4 votes |
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; }
Example 14
Source File: ReactTextView.java From react-native-GPay with MIT License | 4 votes |
@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; }
Example 15
Source File: LinkMovement.java From RefreashTabView with Apache License 2.0 | 4 votes |
@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; }
Example 16
Source File: LongPressLinkMovementMethod.java From Markdown with MIT License | 4 votes |
@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); }
Example 17
Source File: CountLinkMovementMethod.java From timecat with Apache License 2.0 | 4 votes |
@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); }
Example 18
Source File: Touch.java From android_9.0.0_r45 with Apache License 2.0 | 4 votes |
/** * 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); }
Example 19
Source File: TweetTextView.java From catnut with MIT License | 4 votes |
@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; }
Example 20
Source File: LinkMovementMethod.java From ForPDA with GNU General Public License v3.0 | 4 votes |
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; }