是否可以获取 TextView 的文本 Rects?

Is it possible to get the text Rects of a TextView?

假设我有一个这样的TextView

如您所见,文本分为三行。

有什么方法可以获取 Rects? As this text is broken into three lines, I would need three Rects 中的文本区域。

需要强调的是,a Rect的左边是该行第一个字符的左边,右边是该行最后一个字符的右边。

我会按如下方式进行(在 Kotlin 中):

    var lineStart = 0
    var lineEnd = 0
    var lineText = ""
    val paint = textView.paint
    val rectList = arrayListOf<Rect>()

    for (i in 0 until textView.lineCount) {
        lineStart = textView.layout.getLineStart(i)
        lineEnd = textView.layout.getLineEnd(i)
        lineText = textView.text.substring(lineStart, lineEnd)

        val rect = Rect()
        paint.getTextBounds(lineText, 0, lineText.length - 1, rect)
        rectList.add(rect)
    }

Onik 的想法是对的,但结果都是相对于零的。如果您想知道 TextView 的文本在 canvas 中的什么位置,您将需要做更多的计算。

这是一个自定义 TextView,它将在屏幕上显示文本轮廓。

class CustomTextView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.textViewStyle
) : AppCompatTextView(context, attrs, defStyleAttr) {
    private val mPaint = Paint().apply {
        strokeWidth = 2f
        style = Paint.Style.STROKE
        color = Color.RED
    }
    private val mLineOutline = Rect()

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        canvas.save()
        // This is the view's padding which we want to ignore.
        canvas.translate(totalPaddingLeft.toFloat(), totalPaddingTop.toFloat())
        for (line in 0 until lineCount) {
            // This gets the outline of the text on a line but it is all relative to zero.
            paint.getTextBounds(
                text.toString(), layout.getLineStart(line), layout.getLineEnd(line), mLineOutline
            )
            canvas.save()
            // We have the outline relative to zero, shift it so it outlines the text.
            canvas.translate(layout.getLineLeft(line), layout.getLineBaseline(line).toFloat())
            canvas.drawRect(mLineOutline, mPaint)
            canvas.restore()
        }
        canvas.restore()
    }
}

这是显示的内容:

你可能不需要这个 TextView,但你可以获取它的计算。

我发现 this 在思考 Android 排版时发帖很有帮助。