前言
项目中碰到一个问题,需要在自定义View的中央绘制文字;算出了文字的高度,宽度,用自定义View的中心点坐标,减去1/2的高度(宽度)来作为起始坐标绘制文字,结果发现文字垂直方向不居中显示。
代码分析
出错的代码如下:
//测量字符串长度
float textLength = textPaint.measureText(text);
//把文本画在圆心居中
canvas.drawText(text, x - textLength/2, y+mTextSize/2, textPaint);
从效果上看,水平方向是居中的,但是垂直方向上的偏移量有问题,这里的偏移量是通过textSize获取的。
Android文本绘制原理介绍
android中的文字绘制是相对于图中的Baseline绘制的。bottom-top的高度是字体高度(textSize)
-
drawText函数说明
这里的(x, y)的具体位置是Baseline上三个点中的一个(具体根据TextAlign的取值确定)
代码实现
所以这个问题的根源就是我们drawText中的x,y的含义弄错了;可用如下代码找到Baseline位置,并居中显示
Rect rect = new Rect(100,100,500,500);//画一个矩形
Paint rectPaint = new Paint();
rectPaint.setColor(Color.BLUE);
rectPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(rect, rectPaint);
Paint textPaint = new Paint();
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(50);
textPaint.setStyle(Paint.Style.FILL);
//该方法即为设置基线上那个点到底是left,center,还是right 这里我设置为center
textPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float top = fontMetrics.top;//为基线到字体上边框的距离,即上图中的top
float bottom = fontMetrics.bottom;//为基线到字体下边框的距离,即上图中的bottom
int baseLineY = (int) (rect.centerY() - top/2 - bottom/2);//基线中间点的y轴计算公式
canvas.drawText("你好世界",rect.centerX(),baseLineY,textPaint);
baseLineY也可以这样计算:
int xPos = (canvas.getWidth() / 2);
int yPos = (int) ((canvas.getHeight() / 2) - ((textPaint.descent() + textPaint.ascent()) / 2)) ;
//((textPaint.descent() + textPaint.ascent()) / 2) is the distance from the baseline to the center.