TextView 绘制高度解析

Android开发过程中有时不可避免的需要自定义绘制text文本,然而我们会发现绘制后的效果显示总会出现上部或下部空余搞不不一致的问题,这是由于文字绘制的格式导致的,如下图:

image.png

标准的英文书写是基于四线三格,其中,我们书写英文的时候,都是以第三条线为基准,也就是说,基线就是这个四线三格中的第三条线!!
而文字的绘制在代码中由Paint.FontMetrics控制的

1、Paint.FontMetrics 基本介绍

官方对该类的解释是:Class that describes the various metrics for a font at a given text size., 意思是说,这玩意儿是绘制文本内容时存储该文本内容位置信息的一个类。这个类中有如下五个字段:


image.png

1、Paint.FontMetrics中字段的含义及示意图

baseLine与Paint.FontMetrics中值对应关系可以通过通过如下代码运行结果得出:

image.png
private void drawLine(Canvas canvas, Paint.FontMetrics fontMetrics, Paint paint, String text, int start, int end, float x,float y) {
        // 计算每一个坐标
        float baseX = y;
        float baseY = y;
        float topY = baseY + fontMetrics.top;
        float ascentY = baseY + fontMetrics.ascent;
        float descentY = baseY + fontMetrics.descent;
        float bottomY = baseY + fontMetrics.bottom;

        float width = paint.measureText(text, 0, text.length());

        // 绘制文本
        canvas.drawText(text.toString(), start, end, baseX, baseY, paint);

        // BaseLine描画
        Paint baseLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        baseLinePaint.setColor(Color.BLACK);
        canvas.drawLine(0, baseY, width, baseY, baseLinePaint);

        // Base描画
        canvas.drawCircle(baseX, baseY, 5, baseLinePaint);

        // TopLine描画
        Paint topLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        topLinePaint.setColor(Color.RED);
        canvas.drawLine(0, topY, width, topY, topLinePaint);

        // AscentLine描画
        Paint ascentLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        ascentLinePaint.setColor(Color.GREEN);
        canvas.drawLine(0, ascentY, width, ascentY, ascentLinePaint);

        // DescentLine描画
        Paint descentLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        descentLinePaint.setColor(Color.YELLOW);
        canvas.drawLine(0, descentY, width, descentY, descentLinePaint);

        // B0ttomLine描画
        Paint bottomLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bottomLinePaint.setColor(Color.BLUE);
        canvas.drawLine(0, bottomY, width, bottomY, bottomLinePaint);
    }

根据上图可知

  • ascent
    文字内容的顶部到基线的距离。即 ascent=文字内容顶部Y坐标 - 基线Y坐标。由于android中坐标系是 右下为正,所以得到的ascent实际是一个负数。
  • descent
    文字内容的底部到基线的距离。即 descent=文字内容底部Y坐标 - 基线Y坐标。
  • 基线
    在图中,基线的坐标用Y表示,实际上,基线的Y坐标=文字内容中间线Y坐标+1/2 (文字内容高度)
  • top
    对应图中 文字所在行的top 坐标
  • bottom
    对应图中 文字所在行的bottom 坐标
    需要注意:如果设置了行间距,且文本内容产生了换行,那么这个bottom 也会将行间距包裹。所以, 图中蓝色的文字内容中间线的Y轴坐标并不一定等于 (bottom+top)/2

因此,文字的高度对称计算

float txtHeight = fontMetrics.bottom - fontMetrics.top;

你可能感兴趣的:(TextView 绘制高度解析)