Augusto Carmo
Augusto Carmo

Reputation: 4964

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

Suppose I have a single TextView like this

enter image description here

As you can see, the text is broken into three lines.

Is there any way that I can get the text areas in Rects? As this text is broken into three lines, I would need three Rects.

It is important to highlight that the left of a Rect is the left of the first character of the line, and the right is the right of the last character of the line.

Upvotes: 1

Views: 292

Answers (2)

Cheticamp
Cheticamp

Reputation: 62831

Onik has the right idea, but the results will all be relative to zero. You will have to do a little more computation if you want to know where in the canvas the text of your TextView lies.

Here is a custom TextView that will outline the text on the screen.

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()
    }
}

This is what is displayed:

enter image description here

You might not need this TextView, but you can grab its computations.

I find this posting very helpful when thinking about Android typography.

Upvotes: 1

Onik
Onik

Reputation: 19949

I'd do it as follows (in 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)
    }

Upvotes: 1

Related Questions