Android绘图drawText垂直居中与FontMetrics

本文介绍了在Android自定义View中如何使用FontMetrics进行文字垂直居中对齐。通过分析FontMetrics的属性,如top、ascent、descent等,计算出文字相对于基线的位置,并调整坐标实现居中效果。示例代码展示了如何绘制标注线以理解这些属性的作用。
自定义了一个MyView控件,重写它的onDraw来绘制一个点,和一串文字。绘制圆的坐标为200,300,绘制文字的坐标也为200,300。
最初以为文字也是以中心为基准的,然后绘制之后发现文字并不是垂直居中的,它的中心与圆心并不在一条水平线上。文字会偏上。
绘制结果如下图

这里就要说到FontMetrics,绘制文本时,使用FontMetrics对象,计算位置的坐标。通过Paint对象的getFontMetrics()方法可以获得到FontMetrics对象,查看这个类的定义
/**
 * 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;
}
我们获得这个对象之后绘制出线来,这里根据FontMetrics的属性值,绘制出标注线来如下。


从绘制的结果可以清晰的看出,五条线之与文字的位置。实际文字的绘制是以baseLine的位置为基准的。
那么要想让文字也以中心为基准,需要让整体下移一些。

现在画了一个点坐标(X,Y),要使文字也在Y垂直居中,可以根据上图算出,descent是之于base的正数值,ascent是之于base的负数,可根据上边公式求出相差的距离Z,最后文字要垂直居就让文字的纵坐标为Y+Z。这样文字与点就是居中对齐了。
下边贴出绘制几条标注线的代码:
@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(Color.rgb(0, 0, 0));
        textPaint.setTextSize(300);
        textPaint.setColor(Color.WHITE);


        // FontMetrics对象

        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();

        String text = "ajg,'hHAé你好";


        // 计算每一个坐标

        float baseX = 0;
        float baseY = 400;
        float topY = baseY + fontMetrics.top;
        float ascentY = baseY + fontMetrics.ascent;
        float descentY = baseY + fontMetrics.descent;
        float bottomY = baseY + fontMetrics.bottom;
        float leadingY = baseY + fontMetrics.leading;

        // 绘制文本
        canvas.drawText(text, baseX, baseY, textPaint);

        // BaseLine描画
        Paint baseLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        baseLinePaint.setTextSize(40);
        baseLinePaint.setColor(Color.RED);
        canvas.drawLine(0, baseY, getWidth(), baseY, baseLinePaint);
        canvas.drawText("baseLine", 0, baseY, baseLinePaint);

        // TopLine描画
        Paint topLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        topLinePaint.setColor(Color.RED);
        topLinePaint.setTextSize(40);
        canvas.drawLine(0, topY, getWidth(), topY, topLinePaint);
        canvas.drawText("top", 0, topY, baseLinePaint);

        // AscentLine描画
        Paint ascentLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        ascentLinePaint.setColor(Color.RED);
        ascentLinePaint.setTextSize(40);
        canvas.drawLine(0, ascentY, getWidth(), ascentY, ascentLinePaint);
        canvas.drawText("ascent", 0, ascentY, ascentLinePaint);

        // DescentLine描画
        Paint descentLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        descentLinePaint.setColor(Color.RED);
        descentLinePaint.setTextSize(40);
        canvas.drawLine(0, descentY, getWidth(), descentY, descentLinePaint);
        canvas.drawText("descent", 0, descentY, descentLinePaint);

        // BottomLine描画
        Paint bottomLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bottomLinePaint.setColor(Color.BLACK);
        bottomLinePaint.setTextSize(40);
        canvas.drawLine(0, bottomY, getWidth(), bottomY, bottomLinePaint);
        canvas.drawText("bottom", 240, bottomY, bottomLinePaint);

        // LeadingLine描画
        Paint leadingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        leadingPaint.setColor(Color.MAGENTA);
        leadingPaint.setTextSize(40);
        canvas.drawLine(0, leadingY, getWidth(), leadingY, leadingPaint);
        canvas.drawText("leading", 240, leadingY, leadingPaint);


//        Paint paint=new Paint();
//        paint.setColor(Color.parseColor("#be8fff"));
//        paint.setTextSize(100);
//        canvas.drawCircle(200, 300, 10, paint);
//        canvas.drawText("云涛", 200, 300, paint);
    } 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值