android文字绘制中,不得不说到的就是文字的基线,baseline,小时候写的四线的英文如下:
其中的第三条线就是文字的基线(baseline),看起来文字好像是坐在上面一样。
绘制文字的方法drawText在前面已经讲过了,这里就不再赘述。
下面看一看android中基线的位置:
红色的是基线,两条红色的交点就是绘制的起点。绘制代码如下:
int baselineX = 100;
int baselineY = 100;
canvas.drawText("just for test", baselineX, baselineY, paint);
canvas.drawLine(baselineX, baselineY, 1000, baselineY, linePaint);
canvas.drawLine(baselineX, baselineY, baselineX, 0, linePaint);
由此可见,一般的图形绘制是以左上角为起点,而文字绘制的时候,指定起点实际上是基线的起点。
在Paint中,有一个setTextAlign的方法,这个方法主要是设置绘制起点于文字所在矩形的位置。
setTextAlign(Align align);
他接收参数Align,值为
Paint.Align.LEFT //绘制起点在文字矩形左边
Paint.Align.CENTER //绘制起点在文字矩形中间
Paint.Align.RIGHT //绘制起点在文字矩形右边
效果分别如下
以上基本讲解了文字区域和基线以及起点的一个关系。
要了解FontMetrics先看如下的一张图:
bottom: 可绘制的最低高度所在线
如上,加上baseline那么文字相关的就有5条线
FontMetrics有如下属性,他们并不是直接对应上面的四条线的y坐标,而是和baseline的相对关系。
public float top;
public float ascent;
public float descent;
public float bottom;
关系如下
那么根据上诉公式可以推出,这四条线的y坐标都等于对应FontMetrics属性+baseline的y坐标。
ascent线Y坐标 = baseline线的y坐标 + fontMetric.ascent;
bottom线Y坐标 = baseline线的y坐标 + fontMetric.bottom;
那么如何得到FontMetrics值呢,代码如下:
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
绘制出如上的线条如下
如何判断文字在绘制中占据的区域。文字不仅仅是占据文字可见的区域,由于上面讲述的几条线条并不是紧贴文字的,所以文字绘制占据的区域实际上比可见局域大。
文字所占据区域的高度,根据上面的内容,就是top线条和bottom线条的间距。那么宽度如何得到呢:
float width = paint.measureText(text);
使用上诉方法,可以测量出具体字符串所对应的宽度。
这里得到的宽,高所组成的矩形,实际上是文字绘制过程中占据的实际大小,比文字可见大小大。那么如何获得紧紧包裹文字可见内容的区域呢,需要使用如下方法:
public void getTextBounds(String text, int start, int end, Rect bounds);
它将会返回字符串可见区域占据的最小的边界。
注意:这个方法返回的rect是以0,0做为基线的坐标,因此要得到文字实际上占据的位置,需要根据绘制起点做适当的平移。
看如下示例图:
代码如下:
//绘制占据局域
float width = paint.measureText(text);
RectF rectF = new RectF(baselineX, top, baselineX + width, bottom);
paint.setColor(Color.RED);
canvas.drawRect(rectF, paint);
//绘制文字可见矩形
Rect minRect = new Rect();
paint.getTextBounds(text, 0, text.length(), minRect);
minRect.left += baselineX;
minRect.right += baselineX;
minRect.top += baselineY;
minRect.bottom += baselineY;
paint.setColor(Color.GREEN);
canvas.drawRect(minRect, paint);
//绘制文字
paint.setColor(Color.BLUE);
canvas.drawText(text, baselineX, baselineY, paint);