一、获取推荐的行距
paint.getFontSpacing()
即获取推荐的两行文字的baseline之间的距离,这个值是系统根据文字的字体和字号自动计算的。
作用:手动绘制多行文字时,在需要换行的时候给y坐标加上这个值来下移文字
canvas.drawText(texts[0],x,y,paint);
canvas.drawText(texts[1],x,y+paint.getFontSpacing(),paint);
二、获取FontMetrics系列信息
paint.getFontMetrics()
FontMetrics主要提供了以下几个文字排印方面的数值:
ascent、descent、top、bottom、leading
baseline:文字显示的基线,文字开始绘制的位置
ascent / descent:限制普通字符的顶部和底部范围,普通字符,上不会高过ascent,下不会低过descent。ascent和descent的值是相对baseline的相对位移,所以ascent的值为负,descent的值为正。
top / bottom:限制所有字形的顶部和底部范围。除了普通字符,有些字形的显示范围是会超过ascent和descent的限制,但它们都在top和bottom两条线的范围内。类似ascent/descent,top和bottom的值也是相对baseline的相对位移,top值为负,bottom值为正。
leading:指的是行的额外间距,即相对于上下相邻的两行,上行的bottom和下行的top的距离。
(ascent和descent的值同时还可以通过paint.ascent()和paint.descent()方法来快捷获取。)
三、FontMetrics和getFontSpacing()
从定义可以看出,上图中两行文字的 font spacing (即相邻两行的 baseline 的距离) 可以通过 bottom - top + leading (top 的值为负,前面刚说过,记得吧?)来计算得出。
但你真的运行一下会发现, bottom - top + leading 的结果是要大于 getFontSpacing() 的返回值的。
两个方法计算得出的 font spacing 竟然不一样?
这并不是 bug,而是因为 getFontSpacing() 的结果并不是通过 FontMetrics 的标准值计算出来的,而是另外计算出来的一个值,它能够做到在两行文字不显得拥挤的前提下缩短行距,以此来得到更好的显示效果。所以如果你要对文字手动换行绘制,多数时候应该选取 getFontSpacing() 来得到行距,不但使用更简单,显示效果也会更好。
四、获取文字的显示范围
getTextBounds(String text, int start, int end, Rect bounds)
text:要测量的文字
start:文字的起始位置
end:文字的结束位置
bounds:存储文字显示范围的对象
paint.setStyle(Paint.Style.FILL);
canvas.drawText(text, offsetX, offsetY, paint);
paint.getTextBounds(text, 0, text.length(), bounds);
bounds.left += offsetX;
bounds.top += offsetY;
bounds.right += offsetX;
bounds.bottom += offsetY;
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(bounds, paint);
五、测量文字的宽度并返回
paint.getMeasureText(String text);
前面有了 getTextBounds(),这里怎么又有一个 measureText()?
如果你用代码分别使用 getTextBounds() 和 measureText() 来测量文字的宽度,你会发现 measureText() 测出来的宽度总是比 getTextBounds() 大一点点。这是因为这两个方法其实测量的是两个不一样的东西。
getTextBounds: 它测量的是文字的显示范围(关键词:显示)。形象点来说,你这段文字外放置一个可变的矩形,然后把矩形尽可能地缩小,一直小到这个矩形恰好紧紧包裹住文字,那么这个矩形的范围,就是这段文字的 bounds。
measureText(): 它测量的是文字绘制时所占用的宽度(关键词:占用)。前面已经讲过,一个文字在界面中,往往需要占用比他的实际显示宽度更多一点的宽度,以此来让文字和文字之间保留一些间距,不会显得过于拥挤。上面的这幅图,我并没有设置 setLetterSpacing() ,这里的 letter spacing 是默认值 0,但你可以看到,图中每两个字母之间都是有空隙的。另外,下方那条用于表示文字宽度的横线,在左边超出了第一个字母 H 一段距离的,在右边也超出了最后一个字母 r(虽然右边这里用肉眼不太容易分辨),而就是两边的这两个「超出」,导致了 measureText() 比 getTextBounds() 测量出的宽度要大一些。
六、测量字符串每个字符的宽度
paint.getTextWidths(String text, float[] widths)
获取字符串中每个字符的宽度,并把结果填入参数 widths。
这相当于 measureText() 的一个快捷方法,它的计算等价于对字符串中的每个字符分别调用 measureText() ,并把它们的计算结果分别填入 widths 的不同元素。
getTextWidths() 同样也有好几个变种,使用大同小异,不再介绍。