Android开发过程中有时不可避免的需要自定义绘制text文本,然而我们会发现绘制后的效果显示总会出现上部或下部空余搞不不一致的问题,这是由于文字绘制的格式导致的,如下图:
image.png
标准的英文书写是基于四线三格,其中,我们书写英文的时候,都是以第三条线为基准,也就是说,基线就是这个四线三格中的第三条线!!
而文字的绘制在代码中由Paint.FontMetrics控制的
1、Paint.FontMetrics 基本介绍
官方对该类的解释是:Class that describes the various metrics for a font at a given text size., 意思是说,这玩意儿是绘制文本内容时存储该文本内容位置信息的一个类。这个类中有如下五个字段:
image.png
1、Paint.FontMetrics中字段的含义及示意图
baseLine与Paint.FontMetrics中值对应关系可以通过通过如下代码运行结果得出:
image.png
private void drawLine(Canvas canvas, Paint.FontMetrics fontMetrics, Paint paint, String text, int start, int end, float x,float y) {
// 计算每一个坐标
float baseX = y;
float baseY = y;
float topY = baseY + fontMetrics.top;
float ascentY = baseY + fontMetrics.ascent;
float descentY = baseY + fontMetrics.descent;
float bottomY = baseY + fontMetrics.bottom;
float width = paint.measureText(text, 0, text.length());
// 绘制文本
canvas.drawText(text.toString(), start, end, baseX, baseY, paint);
// BaseLine描画
Paint baseLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
baseLinePaint.setColor(Color.BLACK);
canvas.drawLine(0, baseY, width, baseY, baseLinePaint);
// Base描画
canvas.drawCircle(baseX, baseY, 5, baseLinePaint);
// TopLine描画
Paint topLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
topLinePaint.setColor(Color.RED);
canvas.drawLine(0, topY, width, topY, topLinePaint);
// AscentLine描画
Paint ascentLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
ascentLinePaint.setColor(Color.GREEN);
canvas.drawLine(0, ascentY, width, ascentY, ascentLinePaint);
// DescentLine描画
Paint descentLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
descentLinePaint.setColor(Color.YELLOW);
canvas.drawLine(0, descentY, width, descentY, descentLinePaint);
// B0ttomLine描画
Paint bottomLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bottomLinePaint.setColor(Color.BLUE);
canvas.drawLine(0, bottomY, width, bottomY, bottomLinePaint);
}
根据上图可知
- ascent
文字内容的顶部到基线的距离。即 ascent=文字内容顶部Y坐标 - 基线Y坐标。由于android中坐标系是 右下为正,所以得到的ascent实际是一个负数。- descent
文字内容的底部到基线的距离。即 descent=文字内容底部Y坐标 - 基线Y坐标。- 基线
在图中,基线的坐标用Y表示,实际上,基线的Y坐标=文字内容中间线Y坐标+1/2 (文字内容高度)- top
对应图中 文字所在行的top 坐标- bottom
对应图中 文字所在行的bottom 坐标
需要注意:如果设置了行间距,且文本内容产生了换行,那么这个bottom 也会将行间距包裹。所以, 图中蓝色的文字内容中间线的Y轴坐标并不一定等于 (bottom+top)/2
因此,文字的高度对称计算
float txtHeight = fontMetrics.bottom - fontMetrics.top;