Measuring text width to be drawn on Canvas ( Android )

80,833

Solution 1

Have you looked at android.graphics.Paint#measureText(String txt)?

Solution 2

Paint paint = new Paint();
Rect bounds = new Rect();

int text_height = 0;
int text_width = 0;

paint.setTypeface(Typeface.DEFAULT);// your preference here
paint.setTextSize(25);// have this the same as your text size

String text = "Some random text";

paint.getTextBounds(text, 0, text.length(), bounds);

text_height =  bounds.height();
text_width =  bounds.width();

Solution 3

Supplemental answer

There is a slight difference between the width returned by Paint.measureText and Paint.getTextBounds. measureText returns a width that includes the glyph's advanceX value padding the beginning and end of the string. The Rect width returned by getTextBounds does not have this padding because the bounds is the Rect that tightly wraps the text.

source

Solution 4

There's actually three different ways of measuring text.

GetTextBounds:

val paint = Paint()
paint.typeface = ResourcesCompat.getFont(context, R.font.kaushanscript)
paint.textSize = 500f
paint.color = Color.argb(255, 3, 221, 252)
val contents = "g"
val rect = Rect()
paint.getTextBounds(contents, 0, 1, rect)
val width = rect.width()

MeasureTextWidth:

val paint = Paint()
paint.typeface = ResourcesCompat.getFont(context, R.font.kaushanscript)
paint.textSize = 500f
paint.color = Color.argb(255, 3, 221, 252)
val contents = "g"
val width = paint.measureText(contents, 0, 1)

And getTextWidths:

val paint = Paint()
paint.typeface = ResourcesCompat.getFont(context, R.font.kaushanscript)
paint.textSize = 500f
paint.color = Color.argb(255, 3, 221, 252)
val contents = "g"
val rect = Rect()
val arry = FloatArray(contents.length)
paint.getTextBounds(contents, 0, contents.length, rect)
paint.getTextWidths(contents, 0, contents.length, arry)
val width = ary.sum()

Note that getTextWidths could be useful if you are trying to determine when to wrap text to the next line.

The measureTextWidth and getTextWidth are equal and have the advanced width that measure that others have posted about. Some consider this space excessive. However, this is very subjective and dependent on the font.

For example the width from measure text bounds may actually look too small:

measure text bounds looks small

However when adding an additional text the bounds for one letter looks normal: measure text bounds looks normal for strings

Images taken from Android Developers Guide to Custom Canvas Drawing

Solution 5

Well I have done in different way:

String finalVal ="Hiren Patel";

Paint paint = new Paint();
paint.setTextSize(40);
Typeface typeface = Typeface.createFromAsset(getAssets(), "Helvetica.ttf");
paint.setTypeface(typeface);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);

Rect result = new Rect();
paint.getTextBounds(finalVal, 0, finalVal.length(), result);

Log.i("Text dimensions", "Width: "+result.width()+"-Height: "+result.height());

Hope this will help you.

Share:
80,833
NioX5199
Author by

NioX5199

Updated on July 08, 2022

Comments

  • NioX5199
    NioX5199 almost 2 years

    Is there a method which returns the width ( in pixels ) of a text to be drawn on an Android canvas using the drawText() method according to the Paint used to draw it?

  • NioX5199
    NioX5199 almost 14 years
    Thanks this is it! I don't know why I skipped it. The purpose was to simply draw a text at the center of the screen. Anyway I just realized I could also have just used setTextAlign(Align.CENTER) on the Paint used to draw the text, it shifts the specified origin to the center of the drawn text. Thanks.
  • Sanjay Manohar
    Sanjay Manohar over 12 years
    Great, thanks, setting Align on the Paint! who would have thought of that...?
  • yeradis
    yeradis over 12 years
    or you can set the Gravity of the textview to Center
  • Merk
    Merk almost 3 years
    Because kerning (space between letters) is dependent on individual letter sequences this will probably only work satisfactorily with fixed with fonts like Courier.