在TextView中查找单个Character的精确坐标

Igo*_*gor 9 android textview android-screen android-canvas

目前我正在使用paintObject.measureText(textCopy.substring(0,i))迭代TextView文本的副本.例如,measureText("abc".substring(0,1))将给出'b'的相对x坐标.我得到的y坐标layout.getLineTop().这是工作,但不准确X坐标非等宽字体.我可以稍微校准,但在每个设备上它的工作方式不同.

我能想到的最好的解决方案是覆盖负责在屏幕上绘制TextView的类,并希望获得绘制到屏幕上的每个字符的坐标.

有谁知道我需要覆盖什么类来完成这个?或者其他一些创意解决方案?

Igo*_*gor 9

好吧,这似乎是一个Paint.measureText()或更深层次的错误.但我FINALLY找到变通的办法:

layout.getPrimaryHorizontal(int offset)
Run Code Online (Sandbox Code Playgroud)

这很容易.您只需使用其使用的文本长度遍历布局.

它将返回行位置的字符REGARDLESS的x.所以我仍然从中得到线条layout.getLineTop().顺便说一下,如果您正在使用layout.getLineTop(),请注意有一些奇怪的行为,可能是一个错误.我在这里提交了一份错误报告.


Gib*_*olt 6

Java解决方案

这是如何获取特定字符的x和坐标的完整代码。是的文本中所需字符的索引。这些坐标是相对于父容器的yoffsettextView

Layout layout = textView.getLayout();
if (layout == null) { // Layout may be null right after change to the text view
    // Do nothing
}

int lineOfText = layout.getLineForOffset(offset);
int xCoordinate = (int) layout.getPrimaryHorizontal(offset);
int yCoordinate = layout.getLineTop(lineOfText);
Run Code Online (Sandbox Code Playgroud)

Kotlin 扩展函数

如果您希望多次使用它:

fun TextView.charLocation(offset: Int): Point? {
    layout ?: return null // Layout may be null right after change to the text view

    val lineOfText = layout.getLineForOffset(offset)
    val xCoordinate = layout.getPrimaryHorizontal(offset).toInt()
    val yCoordinate = layout.getLineTop(lineOfText)
    return Point(xCoordinate, yCoordinate) 
}
Run Code Online (Sandbox Code Playgroud)

注意:为了确保布局不为空,您可以textview.post(() -> { /* get coordinates */ })在Java或textview.post { /* get coordinates */ }Kotlin中调用