I need two TextViews to have same baseline, ascent, bottom, descent values. Is it possible to change the FontMetrics of TextView after text has been drawn?
-
did you check `TextView` docs? is there anything related to "size" ? – pskink Aug 16 '16 at 06:33
-
@pskink I did check. There wasn't any public api related to that. However getPaint() provided the fontmetrics values. I was wondering if we could change it inside the paint object. – Siva Aug 16 '16 at 06:36
-
nothing related to size in `TextView` api? – pskink Aug 16 '16 at 06:37
-
There are apis related to textSize. But there is no api that could allow us to change Fontmetrics. For instance, if i want to draw text with 5 pixels above baseline, i cannot achieve it with textSize apis. – Siva Aug 16 '16 at 06:40
-
so use `android.text.Spannable` and "spans" concept for such things – pskink Aug 16 '16 at 06:56
2 Answers
It is so late, but I also confronted with this issue, and I solve with some tricks. (just modify baseline
, not ascent, descent or something)
note that
fontMetrics' values
(ascent, descent, bottom, top) are depend ontextSize
.so we must use
fontMetrics' values
afterview is drawn
. (if it is autoSizing or something)to do something after view drawn, using Sa Qada's answer
baseline is always 0.
descent, ascent, top, bottom is relative values.refer this Suragch's answer.
change fontMetrics' values does not affect to UI.
to set custom baseline(text position of textview), just use padding. below code is align to baseline with two TextView.
// this is kotlin code, but I'm sure you can understand // align textview2 to textview1's baseline val tv1Baseline = tv1.paddingBottom + tv1.paint.fontMetrics.bottom val tv2Baseline = tv2.paddingBottom + tv2.paint.fontMetrics.bottom val newPaddingOffset = tv1Baseline - tv2Baseline tv2.setPadding(tv2.paddingLeft, tv2.paddingTop, tv2.paddingRight, tv2.paddingBottom + newPaddingOffset)

- 517
- 6
- 17
-
-
@Siva but this may not really good idea. because you must consider text's alignment case by case. – mgcation Jan 12 '18 at 14:22
-
-
@sandrstar As I know, baselines are always 0. so I just add bottom padding to align two textviews. So it aligns bottoms as you said. – mgcation Jun 03 '18 at 09:14
-
Looks like it's not, I've just checked and at least in my case (code in my answer) return value from getBaseline() is different from 0, since it's 'Return the offset of the widget's text baseline from the widget's top boundary' (https://developer.android.com/reference/android/widget/TextView) – sandrstar Jun 03 '18 at 11:04
-
@sandrstar Thanks for your explanation. I think you're right. My second section(baseline always 0) is just for fontMetrics(textPaint), not textview. by the way, can I ask 1 question? Is your code also work at when layout does not support baseline alignment? – mgcation Jun 03 '18 at 17:45
-
1I think so. I'm using it in my custom layout in order to align two textviews baselines. It does use TextView baseline calculations, but not align_baseline parameter. Obviously, if layout does support baseline alignment, you don't need to use such tricks as in my (or initially yours) answer. – sandrstar Jun 04 '18 at 04:24
Here's solution to align baselines (note the difference from bottom in Suragch answer and definition of return value of TextView.getBaseline()) which alignes tv2 baseline to tv1s':
private void alignWeatherTextBaseline(View tv1, View tv2) {
int tv1Baseline = tv1.getTop() + tv1.getBaseline();
int tv2Baseline = tv2.getTop() + tv2.getBaseline();
int newPaddingOffset = tv1Baseline - tv2Baseline;
if (newPaddingOffset != 0) {
tv2.setPadding(tv2.getPaddingLeft(),
tv2.getPaddingTop(), tv2.getPaddingRight(),
tv2.getPaddingBottom() - newPaddingOffset);
}
}
Be aware of the following:
- if multiline text is possible, you need to write proper
getLastLineBaseline()
and use it instead of standardgetBaseline()
- you can get invalid value (0 or -1) from getBaseline() if a view hasn't been layout yet

- 12,503
- 8
- 58
- 65