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:
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!
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:
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).