文章目录

  • 文字绘制
  • 绘制文字的方式
  • drawText 绘制文字
  • setTextSize 设置文字大小
  • setTypeface 设置字体
  • setFakeBoldText 是否使用伪粗体
  • setStrikeThruText 设置删除线
  • setUnderlineTex 设置下划线
  • setTextSkewX 设置文字倾斜角度
  • setTextScaleX 设置文字横向缩放
  • setLetterSpacing 设置字符间距
  • setTextAlign 设置文字对齐方式
  • drawTextOnPath 沿着Path绘制文字
  • StaticLayout
  • 文字的测量
  • 文字的 baseline ascent/descent top/bottom
  • getFontSpacing 获取行间距
  • getFontMetrics
  • getTextBounds
  • measureText
  • getTextWidths
  • breakText
  • 文字居中问题


文字绘制

绘制文字的方式

drawText 绘制文字

setTextSize 设置文字大小

  • text:文字内容
  • x / y :文字坐标

android给字画横线_ci

String text = "hello world";

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(30);

canvas.drawText(text, 100, 100, paint);

setTypeface 设置字体

android给字画横线_ci_02

paint.setTypeface(Typeface.DEFAULT);
canvas.drawText(text, 50, 50, paint);
paint.setTypeface(Typeface.DEFAULT_BOLD);
canvas.drawText(text, 100, 100, paint);
paint.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "Satisfy-Regular.ttf"));
canvas.drawText(text, 150, 150, paint);

setFakeBoldText 是否使用伪粗体

之所以叫伪粗体( fake bold ),因为它并不是通过选用更高 weight 的字体让文字变粗,而是通过程序在运行时把文字给「描粗」了。

android给字画横线_自定义_03

paint.setFakeBoldText(false);
canvas.drawText(text, 100, 100, paint);
paint.setFakeBoldText(true);
canvas.drawText(text, 100, 100, paint);

setStrikeThruText 设置删除线

android给字画横线_android给字画横线_04

paint.setStrikeThruText(true);
canvas.drawText(text, 100, 100, paint);

setUnderlineTex 设置下划线

android给字画横线_android给字画横线_05

paint.setUnderlineText(true);
canvas.drawText(text, 100, 100, paint);

setTextSkewX 设置文字倾斜角度

android给字画横线_自定义_06

paint.setTextSkewX(-0.5F);
canvas.drawText(text, 100, 100, paint);

setTextScaleX 设置文字横向缩放

android给字画横线_文字绘制_07

paint.setTextScaleX(1);
canvas.drawText(text, 100, 100, paint);
paint.setTextScaleX(0.5F);
canvas.drawText(text, 100, 180, paint);
paint.setTextScaleX(1.5F);
canvas.drawText(text, 100, 260, paint);

setLetterSpacing 设置字符间距

android给字画横线_自定义_08

canvas.drawText(text, 100, 100, paint);
paint.setLetterSpacing(0.2F);
canvas.drawText(text, 100, 180, paint);

setTextAlign 设置文字对齐方式

android给字画横线_行间距_09

paint.setTextAlign(Paint.Align.LEFT);
canvas.drawText(text, 100, 100, paint);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text, 100, 180, paint);
paint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(text, 100, 260, paint);

drawTextOnPath 沿着Path绘制文字

android给字画横线_文字绘制_10

String text = "hello world java android kotlin html css javascript";

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(26);

Path path = new Path();
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(200, 300);
path.lineTo(400, 300);
path.lineTo(400, 400);

canvas.drawTextOnPath(text, path, 0, 0, paint);

StaticLayout

Canvas#drawText()只能绘制单行文字,不能换行,同时换行符\n换行只是加了一个空格。

如果需要绘制多行文字,需要使用StaticLayoutStaticLayoutandroid.text.Layout的子类。

  • width:文字区域宽度,文字达到这个宽度会自动换行
  • align:文字的对齐方向
  • spacingmult:行间距的倍数,通常情况为1
  • spacingadd:行间距的额外增加至,通常情况为0
  • includepad:是否在文字上下添加额外的控件,避免某些过高的文字出现越界

android给字画横线_自定义_11

TextPaint textPaint = new TextPaint();
textPaint.setTextSize(30);

String text1 = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";
StaticLayout staticLayout1 = new StaticLayout(text1, textPaint, 600, Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
String text2 = "a\nbc\ndefghi\njklm\nnopqrst\nuvwx\nyz";
StaticLayout staticLayout2 = new StaticLayout(text2, textPaint, 600, Layout.Alignment.ALIGN_NORMAL, 1, 0, true);

canvas.save();
canvas.translate(50, 50);
staticLayout1.draw(canvas);
canvas.translate(0, 200);
staticLayout2.draw(canvas);
canvas.restore();

文字的测量

文字的 baseline ascent/descent top/bottom

android给字画横线_自定义_12

  • baseline:文字显示的基线
  • ascent / descent:限制普通字符的顶部和底部范围。一般字符情况,上不会高过ascent,下不会低于descent
  • top / bottom:限制所有字符的顶部和底部范围

getFontSpacing 获取行间距

行间距指两行文字的baseline的距离。这个值是系统根据文字的字体和字号自动计算的。

android给字画横线_android给字画横线_13

String text1 = "hello world";
String text2 = "哈喽 世界";
canvas.drawText(text1, 100, 100, paint);
canvas.drawText(text2, 100, 100 + paint.getFontSpacing(), paint);

getFontMetrics

获取Paint的FontMetrics,FontMetrics提供ascent,descent,top,bottom,leading。

getTextBounds

获取文字的显示范围

  • text:需要测量的文字
  • start / end:文字的开始和结束位置
  • bounds:存储文字的显示范围

android给字画横线_自定义_14

int x = 100;
int y = 100;
canvas.drawText(text, x, y, paint);

Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
bounds.left += x;
bounds.top += y;
bounds.right += x;
bounds.bottom += y;
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.RED);
canvas.drawRect(bounds, paint);

measureText

测量文字的宽度

  • getTextBounds: 它测量的是文字的显示范围(关键词:显示)。形象点来说,你这段文字外放置一个可变的矩形,然后把矩形尽可能地缩小,一直小到这个矩形恰好紧紧包裹住文字,那么这个矩形的范围,就是这段文字的 bounds。
  • measureText(): 它测量的是文字绘制时所占用的宽度(关键词:占用)。前面已经讲过,一个文字在界面中,往往需要占用比他的实际显示宽度更多一点的宽度,以此来让文字和文字之间保留一些间距,不会显得过于拥挤。上面的这幅图,我并没有设置 setLetterSpacing() ,这里的 letter spacing 是默认值 0,但你可以看到,图中每两个字母之间都是有空隙的。另外,下方那条用于表示文字宽度的横线,在左边超出了第一个字母 H 一段距离的,在右边也超出了最后一个字母 r(虽然右边这里用肉眼不太容易分辨),而就是两边的这两个「超出」,导致了 measureText()getTextBounds() 测量出的宽度要大一些。

android给字画横线_行间距_15

int x = 100;
int y = 100;
canvas.drawText(text, x, y, paint);
float textWidth = paint.measureText(text);
paint.setColor(Color.RED);
canvas.drawLine(x, y, x + textWidth, y, paint);

getTextWidths

获取每个字符的宽度

float[] charWidths = new float[text.length()];
paint.getTextWidths(text, charWidths);

breakText

breakText() 是在给出宽度上限的前提下测量文字的宽度。如果文字的宽度超出了上限,那么在临近超限的位置截断文字。

android给字画横线_文字绘制_16

int measuredCoubnt;
float[] measuredWidth = {0};
measuredCoubnt = paint.breakText(text, 0, text.length(), true, 300, measuredWidth);
canvas.drawText(text, 0, measuredCoubnt, 100, 100, paint);

文字居中问题

ascent到descent之间到范围为文字的核心区域

android给字画横线_android给字画横线_17

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    //设置水平居中
    paint.setTextAlign(Paint.Align.CENTER);

    //绘制圆环
    float radius = 200;
    paint.setStyle(Paint.Style.STROKE);
    paint.setColor(Color.BLUE);
    paint.setStrokeWidth(10);
    canvas.drawCircle(getWidth() / 2F, getHeight() / 2F, radius, paint);

    //绘制文字并居中
    paint.setStyle(Paint.Style.FILL);
    paint.setTextSize(30);
    String text = "100%";

    //方式一:适合静态文字
    Rect bounds = new Rect();
    paint.getTextBounds(text, 0, text.length(), bounds);
    canvas.drawText(text, getWidth() / 2, getHeight() / 2 - (bounds.top + bounds.bottom) / 2, paint);

    //方式二:适合动态文字
    //        Paint.FontMetrics fontMetrics = new Paint.FontMetrics();
    //        paint.getFontMetrics(fontMetrics);
    //        canvas.drawText(text, getWidth() / 2F, getHeight() / 2F - (fontMetrics.ascent + fontMetrics.descent) / 2, paint);
}