10

我有TextView一个OnTouchListener. 我想要的是当我得到MotionEvent. 有什么办法可以得到底层的字体度量TextView

4

3 回答 3

25

你有没有尝试过这样的事情:

Layout layout = this.getLayout();
if (layout != null)
{
    int line = layout.getLineForVertical(y);
    int offset = layout.getOffsetForHorizontal(line, x);

    // At this point, "offset" should be what you want - the character index
}

希望这可以帮助...

于 2011-04-28T10:13:09.777 回答
5

我不知道执行此操作的简单直接方法,但是您应该能够通过调用TextView.getPaint()使用 TextView 的Paint对象将某些东西放在一起

一旦你有了绘画对象,你就可以通过调用 Paint.getFontMetrics() 来访问底层的 FontMetrices,并可以访问其他函数,如 Paint.measureText() Paint.getTextBounds() 和 Paint.getTextWidths() 来访问显示文本的实际大小。

于 2010-02-20T17:04:55.320 回答
4

虽然它通常有效,但我对 Tony Blues 的回答有一些问题。

首先getOffsetForHorizo​​ntal返回一个偏移量,即使 x 坐标超出该行的最后一个字符。

其次,返回的字符偏移量有时属于下一个字符,而不是指针正下方的字符。显然,该方法返回最近光标位置的偏移量。这可能在角色的左侧或右侧,具体取决于附近的内容。

我的解决方案使用getPrimaryHorizo​​ntal来确定某个偏移量的光标位置,并使用二进制搜索来查找指针 x 坐标下方的偏移量。

public static int getCharacterOffset(TextView textView, int x, int y) {
    x += textView.getScrollX() - textView.getTotalPaddingLeft();
    y += textView.getScrollY() - textView.getTotalPaddingTop();

    final Layout layout = textView.getLayout();

    final int lineCount = layout.getLineCount();
    if (lineCount == 0 || y < layout.getLineTop(0) || y >= layout.getLineBottom(lineCount - 1))
        return -1;

    final int line = layout.getLineForVertical(y);
    if (x < layout.getLineLeft(line) || x >= layout.getLineRight(line))
        return -1;

    int start = layout.getLineStart(line);
    int end = layout.getLineEnd(line);

    while (end > start + 1) {
        int middle = start + (end - start) / 2;

        if (x >= layout.getPrimaryHorizontal(middle)) {
            start = middle;
        }
        else {
            end = middle;
        }
    }

    return start;
}

编辑:这个更新的版本在不自然的换行符下效果更好,当一个长的单词不适合一行并且在中间的某个地方被分割时。

警告:在带连字符的文本中,单击行尾的连字符会返回其旁边字符的索引。此方法也不适用于 RTL 文本。

于 2018-04-06T12:05:21.890 回答