上两篇文章主要介绍了Canvas如何绘制图片以及绘制图片的两种实现方式,本篇文章主要学习Canvas如何绘制文字。
Android自定义控件探索之旅一7
Android自定义控件探索之旅一6
Android自定义控件探索之旅一5
Android自定义控件探索之旅一4
Android自定义控件探索之旅一3
Android自定义控件探索之旅一2
Android自定义控件探索之旅一1
既然涉及到了文字,那么首先捋一捋CharSequence、StringBuffer、StringBuilder、String那千丝万缕般的关系。
首先看一下StringBuffer、StringBuilder、String的类结构源码:
public final class StringBuffer extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
//...StringBuffer类结构...
}
public final class StringBuilder extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
//...StringBuilder类结构...
}
public final class String implements java.io.Serializable, Comparable,
CharSequence {
//...String类结构...
}
一图胜千言,如下图:
可以看到,String、StringBuffer、StringBuilder都实现了CharSequence这个接口,另外,通过String、StringBuffer、StringBuilder的源码可以得知(只需要看类注释即可)StringBuffer是可变长度字符序列,它是线程安全的但是效率相对较低;StringBuilder是可变长度字符序列,线程不安全但是效率高
言归正传,下面看一下Canvas关于绘制文字的源码:
/**
* Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
* based on the Align setting in the paint.
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
* @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull char[] text, int index, int count, float x, float y,
@NonNull Paint paint) {
super.drawText(text, index, count, x, y, paint);
}
/**
* Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
* based on the Align setting in the paint.
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
* @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
super.drawText(text, x, y, paint);
}
/**
* Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
* based on the Align setting in the paint.
*
* @param text The text to be drawn
* @param start The index of the first character in text to draw
* @param end (end - 1) is the index of the last character in text to draw
* @param x The x-coordinate of the origin of the text being drawn
* @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull String text, int start, int end, float x, float y,
@NonNull Paint paint) {
super.drawText(text, start, end, x, y, paint);
}
/**
* Draw the specified range of text, specified by start/end, with its origin at (x,y), in the
* specified Paint. The origin is interpreted based on the Align setting in the Paint.
*
* @param text The text to be drawn
* @param start The index of the first character in text to draw
* @param end (end - 1) is the index of the last character in text to draw
* @param x The x-coordinate of origin for where to draw the text
* @param y The y-coordinate of origin for where to draw the text
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
@NonNull Paint paint) {
super.drawText(text, start, end, x, y, paint);
}
/**
* Draw the text, with origin at (x,y), using the specified paint, along the specified path. The
* paint's Align setting determins where along the path to start the text.
*
* @param text The text to be drawn
* @param path The path the text should follow for its baseline
* @param hOffset The distance along the path to add to the text's starting position
* @param vOffset The distance above(-) or below(+) the path to position the text
* @param paint The paint used for the text (e.g. color, size, style)
*/
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);
}
/**
* Draw the text, with origin at (x,y), using the specified paint, along the specified path. The
* paint's Align setting determins where along the path to start the text.
*
* @param text The text to be drawn
* @param path The path the text should follow for its baseline
* @param hOffset The distance along the path to add to the text's starting position
* @param vOffset The distance above(-) or below(+) the path to position the text
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
float vOffset, @NonNull Paint paint) {
super.drawTextOnPath(text, path, hOffset, vOffset, paint);
}
/**
* Draw the text in the array, with each character's origin specified by the pos array.
*
* @param text The text to be drawn
* @param index The index of the first character to draw
* @param count The number of characters to draw, starting from index.
* @param pos Array of [x,y] positions, used to position each character
* @param paint The paint used for the text (e.g. color, size, style)
* @deprecated This method does not support glyph composition and decomposition and should
* therefore not be used to render complex scripts. It also doesn't handle
* supplementary characters (eg emoji).
*/
@Deprecated
public void drawPosText(@NonNull char[] text, int index, int count,
@NonNull @Size(multiple = 2) float[] pos,
@NonNull Paint paint) {
super.drawPosText(text, index, count, pos, paint);
}
/**
* Draw the text in the array, with each character's origin specified by the pos array.
*
* @param text The text to be drawn
* @param pos Array of [x,y] positions, used to position each character
* @param paint The paint used for the text (e.g. color, size, style)
* @deprecated This method does not support glyph composition and decomposition and should
* therefore not be used to render complex scripts. It also doesn't handle
* supplementary characters (eg emoji).
*/
@Deprecated
public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
@NonNull Paint paint) {
super.drawPosText(text, pos, paint);
}
通过源码可以得知,Canvas绘制文字的方法实则是调用父类BaseCanvas的绘制文字的方法,那么,Canvas一共有三种实现方式:
- mCanvas.drawText(...);
这种方式主要是指定文本的基线位置(基线x默认在字符串左侧,基线y默认在字符串下方)。
- mCanvas.drawTextOnPath(...);
这种方式是指定一个路径,根据路径绘制文字
- mCanvas.drawPosText(...);
这种实现方式的功能主要是可以分别指定每个文字的位置。但是现在已经标注为过时的API(笔者的Android-SDK版本是26)
而且每个绘制文字的API都需要一个Paint(画笔)来进行搭配使用,因为文字的大小,颜色,字体,对齐方式都需要根据开发需求进行设置,这些属性都可以由画笔(Paint)来进行控制。关于Paint画笔,它的主要API如下:
标题 | 相关方法 | 备注 |
---|---|---|
色彩 | setColor setARGB setAlpha | 设置颜色,透明度 |
大小 | setTextSize | 设置文本字体大小 |
字体 | setTypeface | 设置或清除字体样式 |
样式 | setStyle | 填充(FILL),描边(STROKE),填充加描边(FILL_AND_STROKE) |
对齐 | setTextAlign | 左对齐(LEFT),居中对齐(CENTER),右对齐(RIGHT) |
测量 | measureText | 测量文本大小(注意,请在设置完文本各项参数后调用) |
由于Canvas实现绘制文字的第三种方式Canvas.drawPosText(...)这个方法已经标注为过时,那么下面主要是对第一种和第二种实现方式做详细叙述:
Canvas.drawText(...);
drawText(...)这个方法内的参数比较多,但是仔细区分也是有迹可循(系统源码关于参数的翻译非常详细),首先是文本的数据源;Paint上面也说到了,就是定义属性来绘制文本的画笔;这里的 float x, float y,代表的意思就是:用于绘制文本的原点的x坐标,绘制文本的基线的y坐标;有的方法还多了 int index, int count ,这两个参数的意思分别是,index:在文本中要绘制的第一个字符的索引;count:文本中最后要绘制的字符的索引(count - 1),因此绘制文字的第一种实现方式参考代码如下:
// 创建画笔
Paint textPaint = new Paint();
// 设置颜色
textPaint.setColor(Color.BLACK);
// 设置样式
textPaint.setStyle(Paint.Style.FILL);
// 设置字体大小
textPaint.setTextSize(20);
// 文本(要绘制的内容)
String str = "骑小猪看流星";
// 参数分别为 (文本 基线x 基线y 画笔)
mCanvas.drawText(str,200,200,textPaint);
//截取的字符串索引范围是 0-3 结尾索引要减去1
//因此实际的字符串索引是0-2 ,最终结果是 骑小猪
mCanvas.drawText(str,0,3,200,200,textPaint);
Canvas.drawTextOnPath(...);
首先还是看一下系统源码是怎么介绍这个方法的:使用指定的绘制工具,沿着指定的路径来绘制原点为(x,y)的文本。绘画的对齐设置决定了沿着路径的哪里开始文本。
看完了方法的注释以后,在看一下方法里面涉及到的参数,还是看下系统源码是怎么解释的:
- text:这个是绘制文本的数据源
- path:文本应遵循的基线路径
- hOffset:沿路径添加到文本起始位置的距离
- vOffset:文本定位路径上(-)或下(+)的距离
- paint:用于文字的颜料(如颜色、尺寸、风格)
由于Canvas.drawTextOnPath(...)这种绘制文本的实现方式涉及到了Path,Path这个角色在自定义控件中又非常重要,因此会在下一篇文章花大力气来介绍 Path
关于Canvas绘制文字的实现方式大致介绍到这里。
如果这篇文章对您有开发or学习上的些许帮助,希望各位看官留下宝贵的star,谢谢。
Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果