drawText详解

969 阅读2分钟
使用Canvas的draw***方法去绘制一些图像图形,绘制的坐标是从Canvas左上角开始计算的,但是drawText就不一样,如果你传递进去字符串,会发现文字的位置和你指定的不一样。

传入的其实位置为(0,0),结果文字没显示出来。
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
    super.drawText(text, x, y, paint);
}
这里的x,y其实为下图的BaseLine的坐标即五角心的位置,当我们传入(0,0)时,就会出现上面的情况。

除了基线以外,如上图所示,另外还有四条线,分别是ascent,descent,top,bottom。
ascent = ascent线的y坐标 - baseline线的y坐标;
descent = descent线的y坐标 - baseline线的y坐标;
top = top线的y坐标 - baseline线的y坐标;
bottom = bottom线的y坐标 - baseline线的y坐标;
那ascent,descent,top,bottom这些线的位置要怎么计算出来呢?
Android给我们提供了一个类:FontMetrics,它里面有四个成员变量:
public static class FontMetrics {
    /**
     * The maximum distance above the baseline for the tallest glyph in
     * the font at a given text size.
     */
    public float   top;
    /**
     * The recommended distance above the baseline for singled spaced text.
     */
    public float   ascent;
    /**
     * The recommended distance below the baseline for singled spaced text.
     */
    public float   descent;
    /**
     * The maximum distance below the baseline for the lowest glyph in
     * the font at a given text size.
     */
    public float   bottom;
    /**
     * The recommended additional space to add between lines of text.
     */
    public float   leading;
}
获取所绘文字宽度所占的高度
int height = (int) (bottom - top);
获取所绘文字宽度所占的宽度
int width = (int) mPaint.measureText(text);
最小矩形获取
/**
 * 获取最小矩形
 */
mPaint.getTextBounds(text,0,text.length(),minRect);
/**
 * 这两个宽高与上面的宽高不一样,这个是包裹文字的最小矩形的宽高,比上面的两个数值小
 */
int minwWidth = minRect.width();
int minHeight = minRect.height();

红色区域就是最小的最小矩形,绿色的就是所绘文字的矩形。
计算baseline
1、给定顶点的坐标
int drawTextTop = 600;
/**
 * 因为top = baseLineY + fontMetrics.top,
 * 所以baseLineY = top - fontMetrics.top;
 */
int baseLineY1 = (int) (drawTextTop - fontMetrics.top);
2、给定中心点的位置
/**
 * 给定中心线
 */
int center = 1000;
Paint.FontMetrics fontMetrics2 = mPaint.getFontMetrics();
int baseLine = (int) (center + (fontMetrics2.bottom - fontMetrics2.top)/2 - fontMetrics2.bottom);
fontMetrics2.bottom - fontMetrics2.top表示所绘文字的矩形的高
(fontMetrics2.bottom - fontMetrics2.top)/2则为高的一半
(fontMetrics2.bottom - fontMetrics2.top)/2 - fontMetrics2.bottom)则为中心线到baseline的距离,所以baseline的距离就是center加上这段距离。
千万要记住,这里计算的是距离,不是坐标,不是坐标,不然就难以理解。
绘制多行文字
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    width = w;
    height = h;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
    float top = fontMetrics.top;
    float bottom = fontMetrics.bottom;
    //mPaint.setTextAlign(Paint.Align.CENTER);

    /**
     * 则每一行文字的高度为
     */
    //float height = bottom - top;
    float baseLine = height/3 + (bottom - top)/2 - bottom;

    for (int i = 0; i < strs.length;i++){
        float offset = i * (bottom - top);
        canvas.drawText(strs[i],width/3,baseLine + offset,mPaint);
    }

}
具体代码:[https://github.com/fengyuehan/Test/tree/master/customview/src/main/java/com/example/customview/drawText](https://github.com/fengyuehan/Test/tree/master/customview/src/main/java/com/example/customview/drawText)