Paint绘制文本

参考:https://hencoder.com/ui-1-3/
练习github地址:https://github.com/fandazeng/ViewDemo

Canvas 绘制文字的方式

Canvas 的文字绘制方法有三个:drawText() drawTextRun() 和 drawTextOnPath()。

drawText(String text, float x, float y, Paint paint)

drawText() 是 Canvas 最基本的绘制文字的方法:给出文字的内容和位置, Canvas 按要求去绘制文字。方法的参数很简单: text 是文字内容,x 和 y 是文字的坐标。但需要注意:这个坐标并不是文字的左上角,而是一个与左下角比较接近的位置。

mPaint.setTextSize(100);

//y是基线,文本的左下角,x值没有贴着文本,有一点空隙,往左边一点
canvas.drawText("fanda", 200, 200, mPaint);

drawTextOnPath()

沿着一条 Path 来绘制文字。

drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)

参数里,需要解释的只有两个: hOffset 和 vOffset。它们是文字相对于 Path 的水平偏移量和竖直偏移量,利用它们可以调整文字的位置。例如你设置 hOffset 为 5, vOffset 为 10,文字就会右移 5 像素和下移 10 像素。

StaticLayout

StaticLayout 并不是一个 View 或者 ViewGroup ,而是 android.text.Layout 的子类,它是纯粹用来绘制文字的。 StaticLayout 支持换行,它既可以为文字设置宽度上限来让文字自动换行,也会在 \n 处主动换行。

构造方法:
StaticLayout(CharSequence source, TextPaint paint, int width, Layout.Alignment align, float spacingmult, float spacingadd, boolean includepad)

参数:
width 是文字区域的宽度,文字到达这个宽度后就会自动换行;
align 是文字的对齐方向;
spacingmult 是行间距的倍数,通常情况下填 1 就好;
spacingadd 是行间距的额外增加值,通常情况下填 0 就好;
includeadd 是指是否在文字上下添加额外的空间,来避免某些过高的字符的绘制出现越界。

//align 是文字的对齐方向,默认左对齐,还有居中和右对齐
StaticLayout staticLayout = new StaticLayout("hello\nfanda", mTextPaint,
1100,Layout.Alignment.ALIGN_CENTER, 1, 0, true);

canvas.save();
canvas.translate(200, 200);
staticLayout.draw(canvas);
canvas.restore();

Paint 对文字绘制的辅助

Paint 对文字绘制的辅助,有两类方法:设置显示效果的和测量文字尺寸的。

设置显示效果类

1.setTextSize(float textSize)

设置文字大小。

mPaint.setTextSize(50);
canvas.drawText("fanda", 200, 200, mPaint);
mPaint.setTextSize(60);
canvas.drawText("fanda", 200, 300, mPaint);

2.setTypeface(Typeface typeface)

设置字体,可以设置默认提供的字体样式,也可以使用自定义的字体。

//加粗
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
canvas.drawText("zeng fanda", 200, 200 , mPaint);
//等宽字体
mPaint.setTypeface(Typeface.MONOSPACE);
canvas.drawText("zeng fanda", 200, 300, mPaint);

mPaint.setTypeface(Typeface.SANS_SERIF);
canvas.drawText("zeng fanda", 200, 400, mPaint);

mPaint.setTypeface(Typeface.SERIF);
canvas.drawText("zeng fanda", 200, 500, mPaint);

3.setFakeBoldText(boolean fakeBoldText)

设置字体加粗。

mPaint.setFakeBoldText(false);
canvas.drawText("fanda", 200, 200, mPaint);
mPaint.setFakeBoldText(true);
canvas.drawText("fanda", 200, 300, mPaint);

4.setStrikeThruText(boolean strikeThruText)

是否加删除线。

mPaint.setStrikeThruText(true);
canvas.drawText("fanda", 200, 300, mPaint);

5.setUnderlineText(boolean underlineText)

是否加下划线。

mPaint.setUnderlineText(true);
canvas.drawText("fanda", 200, 300, mPaint);

6.setTextSkewX(float skewX)

设置文字倾斜度。

mPaint.setTextSkewX(-0.3f);
canvas.drawText("fanda", 200, 300, mPaint);

7.setTextScaleX(float scaleX)

设置文字横向缩放。

mPaint.setTextScaleX(0.5f);
canvas.drawText("fanda", 200, 300, mPaint);

8.setLetterSpacing(float letterSpacing)

设置字符间距。默认值是 0。

paint.setLetterSpacing(0.2f);  
canvas.drawText(text, 100, 150, paint);

9.setFontFeatureSettings(String settings)

用 CSS 的 font-feature-settings 的方式来设置文字。

paint.setFontFeatureSettings("smcp"); // 设置 "small caps"  
canvas.drawText("Hello HenCoder", 100, 150, paint);  

10.setTextAlign(Paint.Align align)

设置文字的对齐方式。一共有三个值:LEFT CETNER 和 RIGHT。默认值为 LEFT。

mPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText("hello fanda", 700, 200, mPaint);

mPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("hello fanda", 700, 300, mPaint);

mPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText("hello fanda", 700, 400, mPaint);

11.setTextLocale(Locale locale)

设置绘制所使用的语言。Canvas 绘制的时候,默认使用的是系统设置里的 Locale。而通过
Paint.setTextLocale(Locale locale) 就可以在不改变系统设置的情况下,直接修改绘制时的 Locale。

paint.setTextLocale(Locale.CHINA); // 简体中文  
canvas.drawText(text, 150, 150, paint);  
paint.setTextLocale(Locale.TAIWAN); // 繁体中文  
canvas.drawText(text, 150, 150 + textHeight, paint);  
paint.setTextLocale(Locale.JAPAN); // 日语  
canvas.drawText(text, 150, 150 + textHeight * 2, paint); 

测量文字尺寸类

getFontSpacing()

获取推荐的行距。即推荐的两行文字的 baseline 的距离。这个值是系统根据文字的字体和字号
自动计算的。它的作用是当你要手动绘制多行文字(而不是使用 StaticLayout)的时候,可以
在换行的时候给 y 坐标加上这个值来下移文字。

canvas.drawText("hello fanda", 500, 200, mPaint);

canvas.drawText("hello fanda", 500, 200 + mPaint.getFontSpacing(), mPaint);

canvas.drawText("hello fanda", 500, 200 + mPaint.getFontSpacing() * 2, mPaint);

getTextBounds(String text, int start, int end, Rect bounds)

获取文字的显示范围。

参数里,text 是要测量的文字,start 和 end 分别是文字的起始和结束位置,bounds 是存储文字显示
范围的对象,方法在测算完成之后会把结果写进 bounds。

mPaint.getTextBounds(content,0,content.length(),mRect);
canvas.drawText(content, 200, 200, mPaint);

mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(3);

Log.d("bounds","left" + mRect.left + "==" + "top" + mRect.top + "==" + "right" + mRect.right + "==" + "bottom" + mRect.bottom);
// 6,-77,511,1 (相对于绘制文本的位置,即相对于左下角[200,200]这个点)
//206,123,711,201
mRect.left += 200;
mRect.right += 200;
mRect.top += 200;
mRect.bottom += 200;
canvas.drawRect(mRect,mPaint);

float measureText(String text)

测量文字的宽度并返回。

mPaint.setTextSize(100);
canvas.drawText(text1, 200, 200, mPaint);
text1_width = mPaint.measureText(text1);

mPaint.setTextSize(150);
mPaint.setColor(Color.RED);
canvas.drawText(text2, 200 + text1_width, 200, mPaint);
text2_width = mPaint.measureText(text2);

mPaint.reset();
mPaint.setTextSize(100);
canvas.drawText(text3, 200 + text1_width + text2_width, 200, mPaint);

练习演示: