android textview基线,Android文字基线(Baseline)算法

本文介绍了Android Canvas中绘制文字时关键参数Baseline的概念,解释了如何计算和应用Baseline,以及如何在不同坐标系下确保文字垂直居中。重点讲解了计算Baseline位置的公式和实际应用示例。
摘要由CSDN通过智能技术生成

引言

Baseline是文字绘制时所参照的基准线只有先确定了Baseline的位置我们才能准确的将文字绘制在我们想要的位置上。Baseline的概念在我们使用TextView等系统控件直接设置文字内容时是用不到的但是如果我们想要在Canvas画布上面绘制文字时Baseline的概念就必不可少了。

我们先了解一下Android中Canvas画布绘制文字的方法如下图

AAffA0nNPuCLAAAAAElFTkSuQmCC

参数示意

text文字内容

x文字从画布上开始绘制的x坐标Canvas是一个原点在左上角的平面坐标系

yBaseline所在的y坐标不少人已开始以为y是绘制文字区域的底部坐标其实是不正确的这是两个概念

paint画笔设置的文字的大小颜色等属性

了解了文字绘制的方法我们现在就了解一下这个参数yBaseline的计算方法。

Baseline的概念

AAffA0nNPuCLAAAAAElFTkSuQmCC

我们看到如果文字的上方有一些特殊的符号比如上图中的~或者是我们汉语拼音中的声调时文字区域又会多出一部分Leading。

因此完整的公式应该是文字的高度=Descent+Ascent+Leading。

其中leading=0所以我们在文字绘制时不需要考虑Leading图中的数值都是距离Baseline的距离在Baseline上方为负值下方为正值。

Baseline位置y轴坐标的计算

为了方便我们对计算过程进行理解我画了一幅帮助图如下

AAffA0nNPuCLAAAAAElFTkSuQmCC

假设我们是在画布Canvas的顶部绘制一行文字规定一行文字的高度是y文字区域的高度是HeightTOP和BOTTOM之间TOP到0和BOTTOM到y的距离相等这样文字才看起来是居中。因此0到y和TOP到BOTTOM的中线是重合的y轴坐标都是y/2。

我们要绘制一行文字时设计必然会告诉我们0到y的距离所以中线的位置也是固定的y/2那么我们设置了Paint的文字大小后Ascent和Descent又能直接得到就可以算出中线到基线的距离公式如下

基线到中线的距离=(Descent+Ascent)/2-Descent = Ascent-Descent)/2

注意实际获取到的Ascent是负数。公式推导过程如下

中线到BOTTOM的距离是(Descent+Ascent)/2这个距离又等于Descent+中线到基线的距离即(Descent+Ascent)/2=基线到中线的距离+Descent。

有了基线到中线的距离我们只要知道任何一行文字中线的位置就可以马上得到基线的位置从而得到Canvas的drawText方法中参数y的值。

我们看这个图baseLine可以这样获取如果我们知道中线的高度就是height/2,那么加上Ascent-Descent)/2就是baseLine的位置这个都是在textView的坐标系里

float textBaseY = height/2+(Math.abs(paint.ascent())-paint.descent())/2;

如果以top和bottom来计算BaseLine:

AAffA0nNPuCLAAAAAElFTkSuQmCC

可以总结:

字内容的坐标系和TextView组件的坐标系是不一样的

字内容是以其父容器的baseline为原点的。

如果我们想自己实现一个TextView,并且实现字内容能够垂直居中我们在画布中绘制文本的时候会调用Canvas.drawText(String text, float x, float y, Paint paint)这个方法其中y的坐标就是上图中baseline的y坐标所以如果我们只是简单地把drawText方法中的y设置为控件高度的1/2是不准确的。实际上:

AAffA0nNPuCLAAAAAElFTkSuQmCCPaint.FontMetrics fontMetrics = mPaint.getFontMetrics();//获得画笔的FontMetrics用来计算baseLine。因为drawText的y坐标代表的是绘制的文字的baseLine的位置

int baseline = (int) ((Height - fontMetrics.bottom - fontMetrics.top) / 2);//计算出在每格index区域竖直居中的baseLine值

参考https://blog.csdn.net/hailuoli/article/details/78558594

https://blog.csdn.net/xude1985/article/details/51532949

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值