Android字体属性Paint.FontMetrics

释放双眼,带上耳机,听听看~!

前言

最近在做需求的时候需要一个日历控件,在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文章

Android 导出data/data目录数据库

2020-2-19 21:20:43

Android文章

Android正则表达式语法

2020-2-21 17:20:59

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索