center text vertically and horizontally with canvas

greywolf82 picture greywolf82 · Feb 27, 2014 · Viewed 18.5k times · Source

I'm trying to align a text in bitmap horizontally and vertically, I read several post but I can't find a solution. The bitmap is a simple image of a circle. I post my current code. More or less it works but the text is not perfectly centered, it seems a bit on the left and a bit on the top, I mean it seems I have to add an offset to move it to the right and to the bottom.

public static float convertDpToPixel(float dp, Context context) {
     Resources resources = context.getResources();
     DisplayMetrics metrics = resources.getDisplayMetrics();
     float px = dp * (metrics.densityDpi / 160f);
     return px;
}    

v = (ImageView) findViewById(R.id.imageView1);
Bitmap b = BitmapFactory.decodeResource(getResources(),
               R.drawable.marker).copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(b);
Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setARGB(255, 0, 0, 0);
textPaint.setTextAlign(Align.CENTER);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
textPaint.setTextSize(convertDpToPixel(9, this));

String text = "30";
int xPos = (canvas.getWidth() / 2);
int yPos = (int) ((canvas.getHeight() / 2) - ((textPaint.descent() +
               textPaint.ascent()) / 2)) ;

canvas.drawText(text, xPos, yPos, textPaint);
v.setImageBitmap(b);

Answer

Merlevede picture Merlevede · Feb 27, 2014

The problem is that you're currently not considering the width and height of the text. If your text is "hello" or "THIS A STRING" you just treat it equally, so that's wrong.

You need to calculate the width and the height of the text, and then shift the text position by half those distances.

For example to center vertically:

Rect r = new Rect();
paint.getTextBounds(text, 0, text.length(), r);
yPos += (Math.abs(r.height()))/2;    // or maybe -= instead of +=, depends on your coordinates

I hope this takes you into the right direction.

EDIT: The origin is interpreted based on the Align setting in the paint. You're using

 textPaint.setTextAlign(Align.CENTER);

So you probably don't need to do any calculations to center horizontally (meaning that for horizontal origin you should use the code you already had).

 int xPos = (canvas.getWidth() / 2);