android.text.Layout#getLineForVertical ( )源码实例Demo

下面列出了android.text.Layout#getLineForVertical ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: LinkTextView   文件: LinkTextView.java
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;
        }
 
源代码2 项目: android_9.0.0_r45   文件: BaseMovementMethod.java
/**
 * 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;
}
 
源代码3 项目: FastTextView   文件: ClickableSpanUtil.java
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;
}
 
源代码4 项目: xifan   文件: ClickLinkMovementMethod.java
@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;
}
 
源代码5 项目: meiShi   文件: NameTouchMovementMethod.java
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);
}
 
源代码6 项目: android_9.0.0_r45   文件: BaseMovementMethod.java
/**
 * 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;
}
 
源代码8 项目: MHViewer   文件: LinkifyTextView.java
@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);
}
 
源代码9 项目: matrix-android-console   文件: HomeActivity.java
@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);
}
 
源代码10 项目: mimi-reader   文件: SelectableLinkMovementMethod.java
@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);
}
 
源代码11 项目: Spyglass   文件: MentionsEditText.java
/**
 * 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;
}
 
源代码12 项目: ForPDA   文件: LinkMovementMethod.java
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;
}
 
源代码13 项目: catnut   文件: TweetTextView.java
@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;
}
 
源代码14 项目: android_9.0.0_r45   文件: Touch.java
/**
 * 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);
}
 
源代码15 项目: chat21-android-sdk   文件: TextViewLinkHandler.java
@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);
    }
 
源代码16 项目: timecat   文件: CountLinkMovementMethod.java
@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);
}
 
源代码17 项目: Markdown   文件: LongPressLinkMovementMethod.java
@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);
}
 
源代码18 项目: RefreashTabView   文件: LinkMovement.java
@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;
}
 
源代码19 项目: react-native-GPay   文件: ReactTextView.java
@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;
}
 
源代码20 项目: timecat   文件: CountLinkMovementMethod.java
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;
}