How to align text vertically?
textY = topLeftY + height/2 - (mPaint.descent() + mPaint.ascent()) / 2
The distance from "baseline" to "center" should be -(mPaint.descent() + mPaint.ascent()) / 2
Example to centre on cx
and cy
:
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);
}
Why doesn't height()/2f
work the same?
exactCentre()
= (top + bottom) / 2f
.
height()/2f
= (bottom - top) / 2f
These would only yield the same result when top
is 0
. This may be the case for some fonts at all sizes, or other fonts at some sizes, but not for all fonts at all sizes.
Based on steelbytes' response, the updated code would look something like:
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);
}
Since drawing text at Y means that the baseline of the text will end up Y pixels down from the origin, what you need to do when you want to center text within a rectangle of (width, height)
dimensions is:
paint.setTextAlign(Paint.Align.CENTER); // centers horizontally
canvas.drawText(text, width / 2, (height - paint.ascent()) / 2, paint);
Keep in mind that the ascent is negative (which explains the minus sign).
This does not take the descent into account, which is usually what you want (the ascent is generally the height of caps above the baseline).