背景
上一篇我分享了一个带动画的百分比圆形控件,里面就涉及到绘制圆,绘制圆弧和绘制文字。三者对比而言,我觉得绘制文字是需要下点小功夫去理解的,在初学自定义View的路上,你是否会有这样的感觉?在绘制文字时,虽然能够画出来,但是总达不到UI的效果,应该说是文字位置不够精准,和UI有些许的差距,其原因就在于drawText这个API你没有理解透彻。今天我们就来讲一讲drawText这个API。
分析
API
drawText(String text, float x, float y, Paint paint)
text:想要绘制的文字
x:原点x坐标
y:原点(基线)y坐标
paint:绘制文字的画笔
解释通俗易懂,要想精准绘制文字,重点就在于原点(x,y)坐标。如何来确定坐标呢,这就涉及到基线的问题,那什么是基线呢?
基线
1.什么是基线

如上图所示,“fghijk”这个文字每个字母的位置都是上下错落,但是整体看上去却很一致,看上去显得很平衡,仿佛遵循了某种规则,而这个规则就是基线(蓝色),那基线怎么确定呢?答案就是找原点(红色),只要原点确定了,基线也就确定了,由图可知,基线不过是过原点的做x轴的水平线罢了
原点
1.如何找原点(x,y)?
说到原点,就不得不说到画笔的文本对齐,画笔有三种文本对齐方式:左对齐,居中,右对齐,上图是默认左对齐方式,下面两张图分别是居中和右对齐,文字对齐方式可以自己设置,通过画笔 Paint.setTextAlign(Paint.Align.RIGHT) 进行设置


可以看到,对齐方式不同,原点的位置不变,文字所在位置也就不同
tips:(以上所有图的原点的x,y坐标都一样,也就是说,都是一个点,只是因为对齐方式不同,原点相对于文字的位置发生了变化)
所以当我们看到UI图时,只要计算出文字的原点,设置好对齐方式,文字就会出现在相应的文字
2.如何求原点(x,y)?
不同的图,选择不同的对齐方式,原点的x坐标就不同,根据已知条件来选择合适的对齐方式,会让你更容易的得出坐标
比如文字靠屏幕左侧,那就选左对齐,x坐标为0,如果文字居中,就选居中对齐,x坐标为屏幕宽的一半
我们以文字居中对齐的示例图来分析,已知条件:文字是屏幕居中显示的,求x,y?
2.1 求x坐标
为了方便,我们就把对齐方式设置为居中,一目了然,x坐标即为屏幕宽的一半
2.2 求y坐标
想要计算y坐标,就需要引入一个类——FontMetrics,这里大致讲一下,有兴趣的可以自行百度,话不多说,看图
咋一看,这个图像不像小时候的四线三格本,其实画笔在绘制文字的时候就是根据这几条线来绘制的,那么这些不同颜色的线是什么?又代表什么含义呢?
FontMetrics 这个类里主要有五个变量,top,ascent,``descent和bottom,leading,这里主要介绍下前四个
top:可绘制的最高高度所在线到基线的距离 (在图中为绿色线,简称T)
ascent :绘制单个字符时,字符应当的最高高度所在线到基线的距离(在图中为黄色线,简称A)
descent:绘制单个字符时,字符应当的最低高度所在线到基线的距离(在图中为红色线,简称D)
bottom:可绘制的最低高度所在线到基线的距离(在图中为灰色线,简称B)
FontMetrics fontMetrics = mPaint.getFontMetrics();
float ascent = fontMetrics.ascent;
float descent = fontMetrics.descent;
float top = fontMetrics.top;
float bottom = fontMetrics.bottom;

tips:因为手机屏幕y轴自上到下数值增大,所以T和A的值均为负数。
其实当你设置画笔的文字大小时候,FontMetrics 中各个线的值其实就已经确定了,画笔根据这些线,来绘制文字
所以,T到B之间的距离可作为文字的高度,那么中线的y坐标即为 (B-T)/2 (因为T为负数)即图中粉红色的线
所以基线的Y坐标为:中线+G = 屏幕的一半+G = 屏幕的一半+(文字高一半-B) =屏幕一半 + (B-T)/2-B
综上,基线y坐标:中线的y + (B-T)/2-B
这只是已知中线y坐标的情况,如果文字和屏幕上对齐,那么我们就可知T线的y,那基线坐标自然就是 T线y-T值 ,上文说到T值为负,其实是屏幕上+T的绝对值
最后
以上就是本文所有内容了,还是那句话,选择适当的对齐方式,根据情况选择合适的求y方式,在计算出原点坐标,那么文字就能精准的绘制在你想要的位置上!
交流
我的GitHub:https://github.com/feyolny
我的简书:https://www.jianshu.com/u/79cb1fd42ea9
我的CSDN:https://blog.csdn.net/feyolny
欢迎大家一起交流!