7

There is a method in Paint class: Paint.getTextBounds() which returns Rect occupied by some text. But according to this answer it returns something different then width/height of TextView.

Q1: Is there a way to get width and height of TextView using Rect returned by Paint.getTextBounds()?

Note, I do need to know width/height precisely. I will be happy to know upper bound of the rect with possible error about 2-3%, but it MUST be not greater (and should work for any phone not depending on screen resolution and pixel density) then TextView bounds

Q2: Is there any other QUICK method of determining width and height of some text with specified textSize?

I know, width can be determined by Paint.measureText(), but this doesn't return height. Height can be determined by creating new StaticLayout with text and then calling StaticLayout.getHeight(), but this is too slow. I need something more quicker.


The background for all of this is making AutoFitTextView which will automaticaly fit text inside its bounds by up- or down-scaling text size, and it should do this quickly, as there will be many of such AutoFitTextViews changed dynamically very quickly.

Community
  • 1
  • 1
Prizoff
  • 4,486
  • 4
  • 41
  • 69

2 Answers2

10

Found a simple and not slow method of determining text width/height drawn with specific Paint that doesn't use StaticLayout.

public int getTextWidth(String text, Paint paint) {
    Rect bounds = new Rect();
    paint.getTextBounds(text, 0, text.length(), bounds);
    int width = bounds.left + bounds.width();
    return width;
}

public int getTextHeight(String text, Paint paint) {
    Rect bounds = new Rect();
    paint.getTextBounds(text, 0, text.length(), bounds);
    int height = bounds.bottom + bounds.height();
    return height;
}

The short simple description of trick: Paint.getTextBounds(String text, int start, int end, Rect bounds) returns Rect which doesn't starts at (0,0). That is, to get actual width of text that will be set by calling Canvas.drawText(String text, float x, float y, Paint paint) with the same Paint object from getTextBounds() you should add the left position of Rect.

Notice this bounds.left - this the key of the problem.

In this way you will receive the same width of text, that you would receive using Canvas.drawText().


Much more detailed explanation is given in this answer.

Community
  • 1
  • 1
Prizoff
  • 4,486
  • 4
  • 41
  • 69
  • 1
    Are these two methods supposed to work as they are? Because "end" is not defined, and the fourth parameter in the getTextBounds call is "Rect bounds". Shouldn't the line rather looke like: "paint.getTextBounds(text, 0, text.length(), bounds);" – ghost23 Mar 26 '13 at 13:36
  • And of cause, this two methods should be combined into one. Also, note that `bounds.left + bounds.width()` actually is the same as `bounds.right` – Prizoff Mar 26 '13 at 13:41
  • 1
    Does this also work if you have text that should be multiple lines? Does the paint know of the width of the view it is drawing into? Static Layout works with in this case, because we send in the width of the view, to get the height. – havchr Sep 04 '13 at 09:29
  • Hi, in case I want to fix my width, then how this can be achieved? – Aada Mar 06 '14 at 07:26
  • @Aada What are you asking about? What width? Where to fix? – Prizoff Mar 07 '14 at 14:29
1

With java I used class FontMetrics.

Font f= new Font("Arial", Font.BOLD, 16);
FontMetrics metric = getFontMetrics(f);


metric.stringWidth("the text I want to measure");
Mitch Bukaner
  • 171
  • 13
  • I found, that FontMetrics can be used to determine top/bottom bounds of font characters... but what is `metrica` in your code? – Prizoff Mar 21 '13 at 18:24
  • Hm, it seems that the only `FontMetrics` class in Android is `Paint.FontMetrics`, and it doesn't have `stringWidth()` method, only `top`/`bottom` attributes... So, it can be used (i.e. `Paint.getFontMetrics().top`) to determine height of the text (and it will count the maximum char height for all the font) , but not width. Anyway, thanks for mentioning this class! – Prizoff Mar 21 '13 at 21:47
  • I suppose that method is in java.awt package – support_ms Nov 19 '13 at 06:54