Android原生绘图(四):文本绘制

2,023 阅读5分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

绘制文字相关:
Paint 相关设置,
Canvas相关设置。

1.Paint绘制文字相关

相关函数

mPaint.setStrokeWidth(10);//设置画笔宽度
mPaint.setColor(Color.BLUE);//设置画笔颜色
mPaint.setStyle(Paint.Style.STROKE);//设置画笔样式

mPaint.setTextSize();//字体大小
mPaint.setTextAlign();//对齐方式
mPaint.setShadowLayer();//阴影
mPaint.setUnderlineText();//是否显示下划线
mPaint.setFakeBoldText();//true 表示粗体,false表示正常
mPaint.setTextSkewX();//float,设置文本在水平方向上的倾斜,负数表示右斜,正数表示左斜
mPaint.setTextScaleX();//设置比例因子,默认为1,当大于1的时候表示横向拉伸,
// 当小于1的时候表示横向压缩。该方法往往用于一些特效字体的显示场合。
mPaint.setStrikeThruText();//设置文本删除线
mPaint.setLetterSpacing();//设置行间距,默认是0.
mPaint.setTypeface();//设置文本字体样式

**暂不讲解**
mPaint.setLinearText();//设置是否打开线性文本标识
mPaint.setHinting();//设置画笔的隐藏模式
mPaint.setFontFeatureSettings();//设置字体的样式,这个样式和CSS样式很类似
mPaint.setStrokeMiter(float miter );//设置笔画的倾斜度

1.1 setStrokeWidth,setColor

画笔越宽字体越宽,画笔颜色决定了文字颜色。

textPaint.setStrokeWidth(7);
textPaint.setColor(Color.BLUE);
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setTextSize(100);

textPaint2.setStrokeWidth(3);
textPaint2.setColor(Color.BLUE);
textPaint2.setStyle(Paint.Style.STROKE);
textPaint2.setTextSize(100);

canvas.drawText("MatumbaMan的博客", 100, 100, textPaint);
canvas.drawText("MatumbaMan的博客", 100, 300, textPaint2);

1.2 setStyle 设置画笔样式

设置画笔样式:分别设置Paint Style 为FILL,FILL_AND_STROKE,STROKE的字体效果

textPaint.setStrokeWidth(3);
textPaint.setColor(Color.BLUE);
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setTextSize(100);

textPaint2.setStrokeWidth(3);
textPaint2.setColor(Color.BLUE);
textPaint2.setStyle(Paint.Style.FILL);
textPaint2.setTextSize(100);

textPaint3.setStrokeWidth(3);
textPaint3.setColor(Color.BLUE);
textPaint3.setStyle(Paint.Style.FILL_AND_STROKE);
textPaint3.setTextSize(100);

canvas.drawText("MatumbaMan的博客", 100, 100, textPaint);
canvas.drawText("MatumbaMan的博客", 100, 300, textPaint2);
canvas.drawText("MatumbaMan的博客", 100, 500, textPaint3);

1.3 setTextSize 设置字体大小

设置不同的字体大小,单位为px,如果使用dp记得转换。

textPaint.setStrokeWidth(3);
textPaint.setColor(Color.BLUE);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(50);

textPaint2.setStrokeWidth(3);
textPaint2.setColor(Color.BLUE);
textPaint2.setStyle(Paint.Style.FILL);
textPaint2.setTextSize(100);

textPaint3.setStrokeWidth(3);
textPaint3.setColor(Color.BLUE);
textPaint3.setStyle(Paint.Style.FILL);
textPaint3.setTextSize(200);

canvas.drawText("MatumbaMan的博客", 100, 100, textPaint);
canvas.drawText("MatumbaMan的博客", 100, 300, textPaint2);
canvas.drawText("MatumbaMan的博客", 100, 500, textPaint3);

1.4 setTextAlign

设置文字对齐方式,取值:align.CENTER、align.LEFT或align.RIGHT三种

对齐方式基于开始绘制的点。

mTextPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText("MatumbaMan的博客",200, 200, mTextPaint);

mTextPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText("MatumbaMan的博客",200, 300, mTextPaint);

mTextPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("MatumbaMan的博客",200, 400, mTextPaint);

1.6 setShadowLayer 设置阴影

setShadowLayer(float radius, float dx, float dy, int shadowColor) 设置阴影

Radius设置角度,dx,dy控制字体的上下左右出现,有正负之分,dx的正负代表右左,dy的正负代表下上。

mTextPaint.setTextAlign(Paint.Align.LEFT);
mTextPaint.setShadowLayer(10, -20, 40, Color.GRAY);
canvas.drawText("MatumbaMan的博客",200, 200, mTextPaint);


mTextPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText("MatumbaMan的博客",200, 300, mTextPaint);

mTextPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("MatumbaMan的博客",200, 400, mTextPaint);

1.7 下划线,粗体,删除线

textPaint.setStrokeWidth(3);
textPaint.setColor(Color.BLUE);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(50);
textPaint.setUnderlineText(true);

textPaint2.setStrokeWidth(3);
textPaint2.setColor(Color.BLUE);
textPaint2.setStyle(Paint.Style.FILL);
textPaint2.setTextSize(100);
textPaint2.setFakeBoldText(true);

textPaint3.setStrokeWidth(3);
textPaint3.setColor(Color.BLUE);
textPaint3.setStyle(Paint.Style.FILL);
textPaint3.setTextSize(200);
textPaint3.setStrikeThruText(true);

canvas.drawText("MatumbaMan的博客", 100, 100, textPaint);
canvas.drawText("MatumbaMan的博客", 100, 300, textPaint2);
canvas.drawText("MatumbaMan的博客", 100, 500, textPaint3);

1.8 setTextSkewX()

参数类型float,设置文本在水平方向上的倾斜,负数表示右斜,正数表示左斜,默认为0,一般斜体设置为-0.25

textPaint.setStrokeWidth(3);
textPaint.setColor(Color.BLUE);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(50);
textPaint.setUnderlineText(true);
textPaint.setTextSkewX(-1);

textPaint2.setStrokeWidth(3);
textPaint2.setColor(Color.BLUE);
textPaint2.setStyle(Paint.Style.FILL);
textPaint2.setTextSize(50);
textPaint2.setFakeBoldText(true);
textPaint2.setTextSkewX(1);

textPaint3.setStrokeWidth(3);
textPaint3.setColor(Color.BLUE);
textPaint3.setStyle(Paint.Style.FILL);
textPaint3.setTextSize(50);
textPaint3.setStrikeThruText(true);

1.9 setTextScaleX()

设置比例因子,默认为1,当大于1的时候表示横向拉伸,小于1时横向压缩。

textPaint.setStrokeWidth(3);
textPaint.setColor(Color.BLUE);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(50);
textPaint.setTextScaleX(2);

textPaint2.setStrokeWidth(3);
textPaint2.setColor(Color.BLUE);
textPaint2.setStyle(Paint.Style.FILL);
textPaint2.setTextSize(50);
textPaint2.setTextScaleX(1);

textPaint3.setStrokeWidth(3);
textPaint3.setColor(Color.BLUE);
textPaint3.setStyle(Paint.Style.FILL);
textPaint3.setTextSize(50);
textPaint3.setTextScaleX(-2);//反向拉伸

canvas.drawText("MatumbaMan的博客", 100, 100, textPaint);
canvas.drawText("MatumbaMan的博客", 100, 300, textPaint2);
canvas.drawText("MatumbaMan的博客", 100, 500, textPaint3);

1.10 setLetterSpacing 字间距设置默认0,需要最低api21支持.

textPaint.setStrokeWidth(3);
textPaint.setColor(Color.BLUE);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(50);
textPaint.setLetterSpacing(0.05f);

textPaint2.setStrokeWidth(3);
textPaint2.setColor(Color.BLUE);
textPaint2.setStyle(Paint.Style.FILL);
textPaint2.setTextSize(50);
textPaint2.setLetterSpacing(0.5f);

textPaint3.setStrokeWidth(3);
textPaint3.setColor(Color.BLUE);
textPaint3.setStyle(Paint.Style.FILL);
textPaint3.setTextSize(50);

canvas.drawText("MatumbaMan的博客", 100, 100, textPaint);
canvas.drawText("MatumbaMan的博客", 100, 300, textPaint2);
canvas.drawText("MatumbaMan的博客", 100, 500, textPaint3);

1.11setTypeface 设置文本字体样式

可以设置系统中已有字体样式,也可以从文件中读取字体。

如何创建TypeFace:

根据系统存在的字体生成Typeface
根据提供的字体名字和style创建typeFace,如果从名字获取的字体信息为null,将使用default字体。
style包含四种样式:NORMAL, BOLD, ITALIC, BOLD_ITALIC

public static Typeface create(String familyName, @Style int style) ;

//从已存在的TypeFace生成新的typeface
public static Typeface create(Typeface family, @Style int style) ;
 
public static @NonNull Typeface create(@Nullable Typeface family,
        @IntRange(from = 1, to = 1000) int weight, boolean italic);

//默认字体样式
public static Typeface defaultFromStyle(@Style int style) {
    return sDefaults[style];
}

读取字体文件,生成TypeFace

//从Asset文件中读取字体文件,创建TypeFace
public static Typeface createFromAsset(AssetManager mgr, String path); 
//从file文件中读取文件创建typeface
public static Typeface createFromFile(@Nullable File file) ;
Typeface typeface1 = Typeface.create("黑体", Typeface.NORMAL);
Typeface typeface2 = Typeface.create("宋体", Typeface.ITALIC);
Typeface typeface3 = Typeface.createFromAsset(getContext().getAssets(), "f.ttf");

textPaint.setStrokeWidth(3);
textPaint.setColor(Color.BLUE);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(50);
textPaint.setLetterSpacing(0.05f);
textPaint.setTypeface(typeface1);

textPaint2.setStrokeWidth(3);
textPaint2.setColor(Color.BLUE);
textPaint2.setStyle(Paint.Style.FILL);
textPaint2.setTextSize(50);
textPaint2.setLetterSpacing(0.5f);
textPaint2.setTypeface(typeface2);

textPaint3.setStrokeWidth(3);
textPaint3.setColor(Color.BLUE);
textPaint3.setStyle(Paint.Style.FILL);
textPaint3.setTextSize(50);
textPaint3.setTypeface(typeface3);

canvas.drawText("MatumbaMan的博客", 100, 100, textPaint);
canvas.drawText("MatumbaMan的博客", 100, 300, textPaint2);
canvas.drawText("MatumbaMan的博客", 100, 500, textPaint3);

2.Canvas相关

2.1简单函数

public void drawText(@NonNull char[] text, int index, 
int count, float x, float y, @NonNull Paint paint) ;

public void drawText(@NonNull String text, float x, float y,
 @NonNull Paint paint) ;

public void drawText(@NonNull String text, int start, 
int end, float x, float y, @NonNull Paint paint) ;

public void drawText(@NonNull CharSequence text, int start, int end, 
                     float x, float y, @NonNull Paint paint);

面四个函数时最简单的绘制text函数。
drawText(@NonNull char[] text, int index, int count, float x, float y, @NonNull Paint paint)
drawText(@NonNull String text, float x, float y,@NonNull Paint paint)

index,count: 表示text数组中从index开始,共count个数的文字绘制。
x,y: 表示在(x,y)的坐标绘制text,这里的x,y不是绘制文本左上角的坐标。
注意:这里的(x,y)坐标不是绘制文本时左上角的坐标,y是baseline

2.2drawTextOnPath

public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
        float hOffset, float vOffset, @NonNull Paint paint) {
    super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
}

public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
        float vOffset, @NonNull Paint paint) {
    super.drawTextOnPath(text, path, hOffset, vOffset, paint);
}

float hOffset : 与路径起始点的水平偏移距离
float vOffset : 与路径中心的垂直偏移量

Path path = new Path();
path.addCircle(300, 300, 200, Path.Direction.CW);

Path path2 = new Path();
path2.addCircle(300, 800, 200, Path.Direction.CW);

Path path3 = new Path();
path3.addCircle(300, 1300, 200, Path.Direction.CW);

canvas.drawTextOnPath("MatumbaMan的博客", path, 0, 0, mTextPaint);
canvas.drawTextOnPath("MatumbaMan的博客", path2, 50, 30, mTextPaint);
canvas.drawTextOnPath("MatumbaMan的博客", path3, -50, -30, mTextPaint);

canvas.drawCircle(300, 300, 200, mPaint2);
canvas.drawCircle(300, 800, 200, mPaint2);
canvas.drawCircle(300, 1300, 200, mPaint2);

2.3 drawTextRun

public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
        int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
    super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint);
}

public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
        int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
    super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint);
}

参数:
text:要绘制的文字
start:从那个字开始绘制
end:绘制到哪个字结束
contextStart:上下文的起始位置。contextStart 需要小于等于 start
contextEnd:上下文的结束位置。contextEnd 需要大于等于 end
x:文字左边的坐标
y:文字的基线坐标
isRtl:是否是 RTL(Right-To-Left,从右向左)