美文网首页理论
Android字体属性Paint.FontMetrics

Android字体属性Paint.FontMetrics

作者: dlihasa | 来源:发表于2020-01-09 14:57 被阅读0次

    前言

    最近在做需求的时候需要一个日历控件,在github上看CalendarView不错,UI部分完全可以由使用者来自定义绘制,绘制过程中遇到了Paint.FontMetrics,梳理一下。

    概念

    FontMetrics 字体度量,该类是Paint的内部类,通过getFontMetrics()方法可获取字体相关属性。

    字体的几个属性
    baseline  Android文本绘制是以baseline为基准的
    ascent   baseline之上至字符最高处的距离,以baseline为基准,负值
    descent   baseline之下至字符最低处的距离,以baseline为基准,正值
    leading   上一行文字的descent到当前行文字的ascent称为行距
    top 最高字符到baseline的值,以baseline为基准,负值
    bottom 最下字符到baseline的值,以baseline为基准,正值

    从网上找了张图,直观看下:

    注:好多文章说top和bottom分别是ascent和descent的最大值,但是我理解不了,我看到各种标注和我的demo示例表现,ascent和descent未达到过top和bottom的值,可能是说这两个值不可能超过top和bottom吧

    分别来看我代码在两个机型上运行出来的示例值:

    2020-01-09 14:23:00.031 17100-17100/com.dhasa.drawabletintdemo D/font: leading:0.0
    2020-01-09 14:23:00.031 17100-17100/com.dhasa.drawabletintdemo D/font: ascent:-74.21875
    2020-01-09 14:23:00.031 17100-17100/com.dhasa.drawabletintdemo D/font: descent:19.53125
    2020-01-09 14:23:00.031 17100-17100/com.dhasa.drawabletintdemo D/font: top:-84.49219
    2020-01-09 14:23:00.031 17100-17100/com.dhasa.drawabletintdemo D/font: bottom:21.679688
    
    01-09 14:26:35.799 10045-10045/com.dhasa.drawabletintdemo D/font: leading:0.0
    01-09 14:26:35.799 10045-10045/com.dhasa.drawabletintdemo D/font: ascent:-69.0625
    01-09 14:26:35.799 10045-10045/com.dhasa.drawabletintdemo D/font: descent:19.0625
    01-09 14:26:35.799 10045-10045/com.dhasa.drawabletintdemo D/font: top:-69.0625
    01-09 14:26:35.799 10045-10045/com.dhasa.drawabletintdemo D/font: bottom:19.0625
    

    很巧,同一份代码,下边这个机型的这组数据数值竟然是相等的,但是一般是不相等的。

    应用代码示例

    文字居中的实例

    public class CenterFontView extends View {
    
        private Paint paint;
        private Rect targetRect;
        private String testString = "测试:LoveJjh2020";
    
        public CenterFontView(Context context) {
            super(context);
            init(context);
        }
    
        private void init(Context context) {
            paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setStrokeWidth(3);
            paint.setColor(Color.RED);
            paint.setTextSize(80f);
            targetRect = new Rect(50,50,1000,200);
        }
    
        public CenterFontView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        public CenterFontView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            paint.setColor(Color.RED);
            canvas.drawRect(targetRect,paint);
            paint.setColor(Color.GREEN);
            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
            Log.d("font", "leading:" + fontMetrics.leading);
            Log.d("font", "ascent:" + fontMetrics.ascent);
            Log.d("font", "descent:" + fontMetrics.descent);
            Log.d("font", "top:" + fontMetrics.top);
            Log.d("font", "bottom:" + fontMetrics.bottom);
    //        float baseline = targetRect.top + (targetRect.bottom - targetRect.top)/2f - (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.top;
            float baseline = targetRect.top + (targetRect.bottom - targetRect.top)/2f + (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
            paint.setTextAlign(Paint.Align.CENTER);
            canvas.drawText(testString,targetRect.centerX(),baseline,paint);
        }
    }
    

    实现效果:


    红配绿真香~

    值得说明一点的是计算文字baseline的过程,两种写法:

    float baseline = targetRect.top + (targetRect.bottom - targetRect.top)/2f 
    - (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.top;
    
    float baseline = targetRect.top + (targetRect.bottom - targetRect.top)/2f 
    + (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
    

    要将文字垂直居中,首先找到文字所在控件的竖直方向的中点,然后加上或者减去文字高度的一半,就是文字需要展示位置的底部或者顶部,在根据baseline和底部或者顶部的差值(fontMetrics.bottom/fontMetrics.top)计算得出画文字的baseline。

    相关文章

      网友评论

        本文标题:Android字体属性Paint.FontMetrics

        本文链接:https://www.haomeiwen.com/subject/sxizoctx.html