Android: Measure Text Height on a Canvas

AgentKnopf picture AgentKnopf · Feb 20, 2012 · Viewed 11.8k times · Source

I am currently working on rendering a Bitmap, that I then want to send to a mobile printer. However, I am struggling with measuring the height of my text, so I can advance the y position appropriately.

My basic bitmap/canvas/paint configuration is this (Font Size is 16 and the dimensions of the bitmap are 200x400 (width x height):

public MyRenderer() {
    // Initialize bitmap
    bitmap = Bitmap.createBitmap(200, 400, Bitmap.Config.ARGB_8888);

    // Initialize canvas
    canvas = new Canvas(bitmap);

    // Initialize brush (Paint instance)
    brush = new Paint();
    brush.setTextSize(16);
    brush.setTypeface(Typeface.SANS_SERIF);
    brush.setColor(Color.BLACK);
    brush.setStyle(Paint.Style.FILL);
    brush.setAntiAlias(true);
    brush.setTextAlign(Align.LEFT);
}

So far so good, now what I want to do is: If I use the Paint's method drawText I need to supply the x and y coordinates. As for x that's zero (assuming left aligned text) but as for y, I'd have to calculate the height of each text I print and add it up, so I can keep track of my current y position.

And this is where it gets odd: I am using the following method to determine the height of a text (using the Paint objected that I initialized previously - it's called "brush"):

public int measureHeight(String text) {
    Rect result = new Rect();
    // Measure the text rectangle to get the height
    brush.getTextBounds(text, 0, text.length(), result);
    return result.height();
}

The above method returns the following values for the following texts:

  1. "Hello World" returns a height of 12
  2. "A camera instance can be used to compute 3D transformations and generate a matrix." returns a height of 16
  3. "Introducing Android Design: The place to learn about principles, building blocks, and patterns for creating world-class Android user interfaces. Whether you're a UI professional or a developer playing that role, these docs show you how to make good design decisions, big and small." returns a height of 16

It makes sense to me, that number 2 and 3 return a greater height than number 1 but if one line has a height of 12 (as number one does) - it makes no sense, that multiple lines have a height of 16 ?

Am I missing something here? There is a convenience method for measuring the width of a text (using an instance of paint and call measureText("myText") which works perfectly, however I am quite at a loss, when it comes to the height, as the above given results don't make any sense to me.

EDIT

I am aware, that getTextBounds probably does no auto-wrapping of multi-lined text, and that's ok, I already wrote a method for splitting text, but even if it just measures one line, the above given length values still seem unlikely.

Answer

devconsole picture devconsole · Feb 20, 2012

I think it is because the "p" in "compute" extends below the baseline whereas "Hello World" only contains letters that are above the baseline.

Since the line distance should not depend on what specific letters your text happens to consist of you are probably looking for Paint.FontMetrics which can be obtained via Paint.getFontMetrics(). Compute descent - ascent + leading to get the recommended baseline distance (because ascent has a negative value).