如何垂直alignment文本?

目标:纯粹的canvas上的Android> = 1.6。

假设我想写一个函数,将绘制(宽度,高度)大的红色矩形,然后在里面画一个黑色的Hello World文本。 我想要文字在矩形的中心视觉。 所以我们试试:

void drawHelloRectangle(Canvas c, int topLeftX, int topLeftY, int width, int height) { Paint mPaint = new Paint(); // height of 'Hello World'; height*0.7 looks good int fontHeight = (int)(height*0.7); mPaint.setColor(COLOR_RED); mPaint.setStyle(Style.FILL); c.drawRect( topLeftX, topLeftY, topLeftX+width, topLeftY+height, mPaint); mPaint.setTextSize(fontHeight); mPaint.setColor(COLOR_BLACK); mPaint.setTextAlign(Align.CENTER); c.drawText( "Hello World", topLeftX+width/2, ????, mPaint); } 

现在我不知道要把drawText的参数放在哪里 ,即我不知道如何垂直alignment文本。

就像是

???? = topLeftY + height / 2 + fontHeight / 2 – fontHeight / 8;

似乎工作或多或less好,但必须有一个更好的办法。

cxcy为中心的示例:

 private final Rect textBounds = new Rect(); //don't new this up in a draw method public void drawTextCentred(Canvas canvas, Paint paint, String text, float cx, float cy){ paint.getTextBounds(text, 0, text.length(), textBounds); canvas.drawText(text, cx - textBounds.exactCenterX(), cy - textBounds.exactCenterY(), paint); } 

为什么不height()/2f工作相同?

exactCentre() = (top + bottom) / 2f

height()/2f = (bottom - top) / 2f

top0时,这只会产生相同的结果。 对于所有尺寸的某些字体或某些尺寸的其他字体,情况可能如此,但不适用于所有尺寸的所有字体。

 textY = topLeftY + height/2 - (mPaint.descent() + mPaint.ascent()) / 2 

从“基线”到“中心”的距离应该是-(mPaint.descent() + mPaint.ascent()) / 2

基于Steelbytes的回应,更新后的代码如下所示:

 void drawHelloRectangle(Canvas c, int topLeftX, int topLeftY, int width, int height) { Paint mPaint = new Paint(); // height of 'Hello World'; height*0.7 looks good int fontHeight = (int)(height*0.7); mPaint.setColor(COLOR_RED); mPaint.setStyle(Style.FILL); c.drawRect( topLeftX, topLeftY, topLeftX+width, topLeftY+height, mPaint); mPaint.setTextSize(fontHeight); mPaint.setColor(COLOR_BLACK); mPaint.setTextAlign(Align.CENTER); String textToDraw = new String("Hello World"); Rect bounds = new Rect(); mPaint.getTextBounds(textToDraw, 0, textToDraw.length(), bounds); c.drawText(textToDraw, topLeftX+width/2, topLeftY+height/2+(bounds.bottom-bounds.top)/2, mPaint); } 

由于在Y处绘制文本意味着文本的基线最终会从原点向下Y像素,所以如果要在(width, height)尺寸的矩形内居中文本,您需要执行的操作是:

 paint.setTextAlign(Paint.Align.CENTER); // centers horizontally canvas.drawText(text, width / 2, (height - paint.ascent()) / 2, paint); 

请记住,上升是负的(这解释了负号)。

这不考虑下降,这通常是你想要的(上升通常是高于基线的高度)。

使用mPaint.getTextBounds(),你可以问绘制的文本有多大,然后使用这个信息,你可以计算出你想要绘制的地方。

 public static PointF getTextCenterToDraw(String text, RectF region, Paint paint) { Rect textBounds = new Rect(); paint.getTextBounds(text, 0, text.length(), textBounds); float x = region.centerX() - textBounds.width() * 0.4f; float y = region.centerY() + textBounds.height() * 0.4f; return new PointF(x, y); } 

用法:

 PointF p = getTextCenterToDraw(text, rect, paint); canvas.drawText(text, px, py, paint);