一、作用
二、概念
1. API
(1)drawText()
// 将字符串[start,end)范围内的字符绘制出来,绘制起点(x,y)
public void drawText (CharSequence text, int start, int end, float x, float y, Paint paint)
(2)drawTextOnPath()
// 将指定字符沿 path 绘制
public void drawTextOnPath (char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint)
(3)drawTextRun()
2. 术语
(1)基线
(2)行间距倍数
Android TextView行间距解析
(3)行间距额外增加值
行间距倍数、行间距额外增加值改变了文字占用的高度,从而在视觉上形成了行与行之间间隔的效果。
public int getLineHeight() {
return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult + mSpacingAdd);
}
(4)和文字绘制相关的5条线
leading
上行的bottom
和下行的top
线距离。
3. StaticLayout
(1)作用
Canvas::drawText()
绘制文字时不能换行:文字不能在 View 边缘自动换行;不能在\n
处换行
StaticLayout
绘制文字时能换行:文字在 View 边缘自动换行;在\n
处换行
(2)构造函数
StaticLayout(CharSequence source, TextPaint paint, int width, Layout.Alignment align, float spacingmult, float spacingadd, boolean includedpad)
// spacingmult :行间距倍数,通常情况下填1就好
// spacingadd:行间距额外增加的数值,通常情况下填0就好
// includedpad:是指是否在文字上下添加额外的空间,来避免某些过高的字符的绘制出现越界
4. Paint 对文字绘制的辅助能力
(1)对文字绘制的辅助
(2)测量文字尺寸类
float getFontSpacing()
获取推荐的行间距,即两行文字的baseline
的距离。这个值是系统根据文字的字体和字号自动计算的。
当你需手动绘制多行文字(而不是使用StaticLayout
时),可以在换行的时候给y
坐标加上这个值来下移文字。
FontMetrics getFontMetrics()
提供几个文字排版方面的数值。
从定义可得,两行文字的 font spacing(即两行文字的baseline
的距离),可以通过bottom-top+leading
计算得出。
但实际上
bottom-top+leading
的结果要大于getFontSpacing()
返回的值。因为:getFontSpacing()
不是通过FontMetric
的标准值计算出来的,而是另外计算出来的一个值,它能够做到在两行文字不显得拥挤的前提下缩短行距,以此来得到更好的显示效果。
所以:如果你需要对文字手动换行绘制,多数时候应该选取
getFontSpacing()
来得到行距,不但使用简单,显示效果也更好。
void getTextBounds(CharSequence text, int start, int end, Rect bounds)
测量文字显示范围
// text:要测量的文字
// start:起始位置
// end:结束位置
// bounds:存储文字显示范围,该方法测量完后将数值存储在该对象中
float measureText(CharSequence text, int start, int end)
测量文字宽度并返回
// text:要测量的文字
// start:起始位置
// end:结束位置
void getTextWidth(String text, int start, int end, int[] widths)
测量字符串中每个字符的宽度,并将结果填充到数组中
int breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth)
根据传入的 maxWidth,测量出能显示的最大字符个数,并返回
三、使用
1.measureText()
float text1Width = paint1.measureText(text1);
float text2Width = paint2.measureText(text2);
canvas.drawText(text1, 50, 200, paint1);
canvas.drawText(text2, 50 + text1Width, 200, paint2);
canvas.drawText(text3, 50 + text1Width + text2Width, 200, paint1);
2.getTextBounds()
结合getTextBounds方法简析绘制文字时需要注意的地方
getTextBounds中bounds的坐标原点
这种居中算法的优点是,可以让文字精准地居中,分毫不差
打印A
、j
,分别调用getTextBounds()
返回的结果
A::top=-114,bot=0,left=2,right=103
j::top=-116,bot=35,left=-6,right=28
- 使用 Paint.getTextBounds() 计算出文字的显示区域
Rect textBounds = new Rect();
paint2.getTextBounds(text, 0, texts.length(), textBounds);
- 计算出文字的
baseline
的y
坐标相对 middle 的偏移量
yOffsets = - (textBounds.top + textBounds.bottom) / 2;
- 绘制文字,让文字在框中上下居中
canvas.drawRect(50, top, getWidth() - 50, bottom, paint1);
int middle = (top + bottom) / 2;
canvas.drawText(texts, 100, middle + yOffsets, paint2);
3.getFontMetrics()
- 使用 Paint.getFontMetrics() 得到
acent
、decent
Paint.FontMetrics fontMetrics = paint2.getFontMetrics();
- 计算出文字的
baseline
的y
坐标相对 middle 的偏移量(计算逻辑同上)
yOffset = - (fontMetrics.ascent + fontMetrics.descent) / 2;
- 绘制文字,让文字在框中上下居中
canvas.drawRect(50, top, getWidth() - 50, bottom, paint1);
int middle = (top + bottom) / 2;
canvas.drawText(text, 100, middle + yOffset, paint2);