关闭

android|图形图像 fontmetrics 文本绘制

标签: androidCanvasFontMetricsAscentDescent
116人阅读 评论(0) 收藏 举报
分类:

`有不少同学对Android 中的文本绘制的相关知识不了解,或者每次当自己想绘制文本时,总是画不出自己想要的效果,根本原因就是对FontMetrics不甚了解,今天就来给大家普及下相关的知识,让大家彻底弄明白文本是如何绘制,以及相关的基础知识,首先看一张图:




大家只用看三个地方,ascent,descent,baseline,其实最重要的就是baseline,如果确认了baseline,我们就能确认文本在垂直方向上的位置。

而baseline的计算需要依赖ascent和descent。大家看的时候,是不是不知道ascent,descent,baseline是什么鬼,那我们来看看FontMetrics,这个类,我们可以通过

Paint.getFontMetrics()接口来获取,先看看源码:

/**
 * Class that describes the various metrics for a font at a given text size.
 * Remember, Y values increase going down, so those values will be positive,
 * and values that measure distances going up will be negative. This class
 * is returned by getFontMetrics().
 */
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;
}

看Android 对FontMetrics的描述,(这里我们不说top和bottom, 因为我么基本上用不着,leading就是每行文本之间的间距)我用刚过四级的英语水平给大家翻译下:用来描述指定文本大小的字体的多个尺寸信息,在Y轴方向,向下,值越大,从某个值开始变成正值,则相反方向的值就是负值(fuck!,我自己都说不清楚了),还是说人话吧,就是从baseline开始,向下就是正值(ascent),向上就是负值(descent), 这里的正值(ascent),负值(descent)都是相对于baseline的,而且大家注意了,这些值与文本内容是没有关系的,跟textsize 是相关的,那么这又绕回来了,baseline是什么鬼呢,baseline是文本绘制的基线,是文本绘制在垂直方向上的基准点,再看一张截图:




图中我把baseline,asent,descent的位置用线画出来了,大家可以对比下我上面说的,但是大家看到了,为什么我画了两个“愚蠢,bankle stupid”,我也不知道,呵呵。其实大家仔细看(红色的方框是View的边界),就知道,第一个“愚蠢,bankle stupid”(等会我会用左边的文本这个说法来代替) 在View中是偏上的,而第二个"愚蠢,bankle stupid”(等会我会用右边的文本这个说法来替代)在View中是居中的,这是怎么回事呢?左边的文本,他的baselise 给的就是 View.getHeight()/2,也就是View的高度的一半,而大家看右边的文本它居中显示了,但是baseline其实是在中线下方的,那么问题来了,baseline的位置如何计算呢,其实也就是图中中线移动到baseline的距离,具体的计算方法是:文本高度的一半减去sescent


 canvas.drawText(content, 0, canvas.getHeight() / 2, paint);

        float contentWidth = paint.measureText(content);

        Paint.FontMetrics fontMetrics = paint.getFontMetrics();

        //开始计算基线的位置
        int baseLine = (int) (canvas.getHeight() / 2 + ((fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent));


        canvas.drawText(content, contentWidth, baseLine, paint);


        //绘制中线
        canvas.drawLine(0, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight() / 2, paint);


        paint.setColor(Color.BLUE);
        canvas.drawLine(contentWidth, baseLine, canvas.getWidth(), baseLine, paint);
        //绘制ascent
        int ascentY = (int) (baseLine + fontMetrics.ascent);
        //绘制sescent
        int descentY = (int) (baseLine + fontMetrics.descent);

        canvas.drawLine(contentWidth, ascentY, canvas.getWidth(), ascentY, paint);
        canvas.drawLine(contentWidth, descentY, canvas.getWidth(), descentY, paint);


        rangeRect.set(0, 0, canvas.getWidth(), canvas.getHeight());

        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(rangeRect, paint);


        Log.v(TAG, "fontMetrics.top " +(fontMetrics.top));
        Log.v(TAG, "fontMetrics.ascent "+(fontMetrics.ascent));

        Log.v(TAG, "fontMetrics.descent " + (fontMetrics.descent));
        Log.v(TAG, "fontMetrics.bottom " + ( fontMetrics.bottom));

图画的有点丑,凑合用大笑





0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:2535次
    • 积分:243
    • 等级:
    • 排名:千里之外
    • 原创:21篇
    • 转载:0篇
    • 译文:2篇
    • 评论:0条