Android自定义View中drawText居中显示

drawText方法参数含义:canvas.drawText(String text, float x, float y, Paint paint),第一个参数是需要绘制的文本,第四个参数是画笔,第二和第三个参数的含义在不同的情况下的值是不一样的,x默认是这个字符串的左边在屏幕的位置,y是指定这个字符基线baseline在屏幕上的位置,如果设置了paint.setTextAlign(Paint.Align.CENTER)那就是字符的中心。

一般来说,自定义View绘制文本时会做如下定义:

1
2
3
4
String mText = "测试文本";
Paint mTextPaint = new Paint();
Rect mTextBound = new Rect();
mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);

绘制居中文本的代码为:

1
2
3
4
canvas.drawText(mText , // text
getMeasuredWidth() / 2 - mTextBound.width() / 2 , // x
getMeasuredHeight() / 2 - mTextBound.height() / 2 , // y
mTextPaint); // paint

然而,这段代码却不能使文字居中,而是往下偏了一点,即y值计算错误。原因是y不是这个字符中心在屏幕上的位置,而是baseline在屏幕上的位置,而代码中y在垂直的中央,这样是不对的。

关于baseline,Android中测量baseline需要用到Paint.FontMetrics这个类:

示意图

  1. 基准点是baseline
  2. ascent:是baseline之上至字符最高处的距离
  3. descent:是baseline之下至字符最低处的距离
  4. leading:是上一行字符的descent到下一行的ascent之间的距离,也就是相邻行间的空白距离
  5. top:是指的是最高字符到baseline的值,即ascent的最大值
  6. bottom:是指最低字符到baseline的值,即descent的最大值

将代码修改如下即可达到文字居中的效果:

1
2
3
4
5
6
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
float baseline = (getMeasuredHeight() - fontMetrics.bottom + fontMetrics.top) / 2 -fontMetrics.top;
canvas.drawText(mText ,
getMeasuredWidth() / 2 - mTextBound.width() / 2 , // x
baseline , // y
mTextPaint);