Android自定义控件探索之旅一6(笔记)

上两篇文章主要介绍了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地址),文章请勿滥用,也希望大家尊重笔者的劳动成果

你可能感兴趣的:(Android自定义控件探索之旅一6(笔记))