结合getTextBounds方法简析绘制文字时需要注意的地方

我们在自定义View的时候时常会重写onDraw方法,那么在onDraw方法中,绘制文字有时候就用到了paint 的getTextBounds方法来确定文字的位置。而这个方法需要注意两点:

1.绘制文字的时候即drawText时

源码:

    /**
     * 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) {
        native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
                paint.getNativeInstance(), paint.mNativeTypeface);
    }
这里面的参数 y  是文字基线(baseline)的y坐标。

2.getTextBounds里的rect参数得到数值后,查看它的属性值 top、bottom会发现top是一个负数;bottom有时候是0,有时候是正数。结合第一点很容易理解,因为baseline坐标看成原点(0,0),那么相对位置top在它上面就是负数,bottom跟它重合就为0,在它下面就为负数。像小写字母j g y等,它们的bounds bottom都是正数,因为它们都有降部(在西文字体排印学中,降部指的是一个字体中,字母向下延伸超过基线的笔画部分)。

理解以上两点用那么getTextBounds就只剩下计算的问题了,下面举个例子演示一遍计算过程。

假如我们绘制一个方框,要求字母J 和 j 在这个方框的正中间,如图

结合getTextBounds方法简析绘制文字时需要注意的地方_第1张图片

绘制之前,就是理解上面的第一点,找到基线的y的坐标就是关键。

先从J开始。

这个比较简单,由于J没有降部,而它的基线正好和它的bottom重合,因此可以理解成将J下移J的一半高度就是正中间位置,如图:

结合getTextBounds方法简析绘制文字时需要注意的地方_第2张图片

找到baseline 的y的值

如果用bounds height计算:

y = middle  + bounds.height/2 

如果用bounds top bottom 计算:

bounds高度(负) = bounds.top(负) + bounds.bottom

y =  middle - bounds高度(负)/2


然后再绘制j。j是有降部的,而且它的bounds的bottom是正数,如果还像上面那么计算向下平移一半高度,最终位置不会是垂直居中的位置,究竟像下移动多少呢,看图说明一下:

结合getTextBounds方法简析绘制文字时需要注意的地方_第3张图片

如果此时还用bounds的height的属性是得不到middle 和 baseline之间这个偏移量的,得不到偏移量那么baseline的y的坐标就拿不到。因此只能用bounds的top和bottom属性。首先利用对称线,我们一目了然就知道这个偏移量需要得到top 和 bottom之间的差值。第一步拿到差值:

distance(负) = bounds.top(负) + bounds.bottom 

这里为了不改变程序中的数值,因此用负数代表,并且与绘制J方法保持一致。

第二步得到偏移量:

offsetY(负) = distance(负) /2;

第三步求得baseline的y的坐标:

y = middle - offsetY (负);

上面两种情况都是遵循同一个目标就是如何得到baseline的y的坐标值,因为这个值就是最终drawText的参数,是开始绘制的坐标。

你可能感兴趣的:(Android基础知识,API)