美文网首页
Android——自定义View——文字绘制

Android——自定义View——文字绘制

作者: 四喜汤圆 | 来源:发表于2020-05-06 21:14 被阅读0次

HenCoder Android 开发进阶:自定义 View 1-3 文字的绘制

一、作用

二、概念

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,测量出能显示的最大字符个数,并返回

三、使用

HenCoder 的练习做完啦

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的坐标原点

这种居中算法的优点是,可以让文字精准地居中,分毫不差

摘自"结合getTextBounds方法简析绘制文字时需要注意的地方"

打印Aj,分别调用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);
  • 计算出文字的baseliney坐标相对 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() 得到acentdecent
Paint.FontMetrics fontMetrics = paint2.getFontMetrics();
  • 计算出文字的baseliney坐标相对 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);

相关文章

网友评论

      本文标题:Android——自定义View——文字绘制

      本文链接:https://www.haomeiwen.com/subject/dgpyghtx.html