Search code examples
androidandroid-layouttextview

Place TextView in center of container based on text bounds


I am trying to programmatically place a TextView in the center of its container where only the text bounds are taken into account, and not the entire TextView rect. See image below:

enter image description here

And my code:

// "workingLayout" is the container on the TextView
val tvv = TextView(this)
tvv.includeFontPadding = false
tvv.setPadding(20, 0, 20, 0)
tvv.gravity = Gravity.CENTER
tvv.text = "ggg"
tvv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 150f)
tvv.setTextColor(Color.BLUE)
tvv.background = resources.getDrawable(R.drawable.edit_text_shape, null)

tvv.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
tvv.x = (workingLayout.width / 2f) - (tvv.measuredWidth / 2)
tvv.y = (workingLayout.height / 2f) - (tvv.measuredHeight / 2)
workingLayout.addView(tvv)

I tried using paint.getTextBounds instead of measure but no luck...

Thanks!


Solution

  • Was able to get it done thanks to this post.

    Basically, paint.getTextBounds result is relative to TextView baseline, and the TextView baseline we can get from textView.baseline, given that we can calculate the text bounding box mid point, and subtract that (instead of TextView mid) from the container mid point.

    Reference drawing:

    enter image description here

    val tv = TextView(this)
    // init TextView
    ...
    ...
    tv.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
    
    // Get text bounding box
    val bbox = Rect()
    tv.paint.getTextBounds(tv.text.toString(), 0, tv.text.toString().length, bbox)
    
    // The distance from textview top to actual text top
    val textInsetTop = tv.baseline + bbox.top
    
    // Text bounding box mid
    val bboxMid = textInsetTop + (bbox.height() / 2f)
    
    // Now can center the TextView in its container
    val containerMid = workingLayout.height / 2f
    tv.y = containerMid - bboxMid
    

    IMPORTANT: This works only for single line text view (and non-scaled).