android canvas drawText set font size from width?

JavaAndroidAndroid Canvas

Java Problem Overview


I want to draw text on canvas of certain width using .drawtext

For example, the width of the text should always be 400px no matter what the input text is.

If input text is longer it will decrease the font size, if input text is shorter it will increase the font size accordingly.

Java Solutions


Solution 1 - Java

Here's a much more efficient method:

/**
 * Sets the text size for a Paint object so a given string of text will be a
 * given width.
 * 
 * @param paint
 *            the Paint to set the text size for
 * @param desiredWidth
 *            the desired width
 * @param text
 *            the text that should be that width
 */
private static void setTextSizeForWidth(Paint paint, float desiredWidth,
        String text) {

    // Pick a reasonably large value for the test. Larger values produce
    // more accurate results, but may cause problems with hardware
    // acceleration. But there are workarounds for that, too; refer to
    // http://stackoverflow.com/questions/6253528/font-size-too-large-to-fit-in-cache
    final float testTextSize = 48f;

    // Get the bounds of the text, using our testTextSize.
    paint.setTextSize(testTextSize);
    Rect bounds = new Rect();
    paint.getTextBounds(text, 0, text.length(), bounds);

    // Calculate the desired size as a proportion of our testTextSize.
    float desiredTextSize = testTextSize * desiredWidth / bounds.width();

    // Set the paint for that size.
    paint.setTextSize(desiredTextSize);
}

Then, all you need to do is setTextSizeForWidth(paint, 400, str); (400 being the example width in the question).

For even greater efficiency, you can make the Rect a static class member, saving it from being instantiated each time. However, this may introduce concurrency issues, and would arguably hinder code clarity.

Solution 2 - Java

Try this:

/**
 * Retrieve the maximum text size to fit in a given width.
 * @param str (String): Text to check for size.
 * @param maxWidth (float): Maximum allowed width.
 * @return (int): The desired text size.
 */
private int determineMaxTextSize(String str, float maxWidth)
{
	int size = 0;		
	Paint paint = new Paint();
	
	do {
		paint.setTextSize(++ size);
	} while(paint.measureText(str) < maxWidth);
	
	return size;
} //End getMaxTextSize()

Solution 3 - Java

Michael Scheper's solution seems nice but it didn't work for me, I needed to get the largest text size that is possible to draw in my view but this approach depends on the first text size you set, Every time you set a different size you'll get different results that can not say it is the right answer in every situation.

So I tried another way:

private float calculateMaxTextSize(String text, Paint paint, int maxWidth, int maxHeight) {
    if (text == null || paint == null) return 0;
    Rect bound = new Rect();
    float size = 1.0f;
    float step= 1.0f;    
    while (true) {
        paint.getTextBounds(text, 0, text.length(), bound);
        if (bound.width() < maxWidth && bound.height() < maxHeight) {
            size += step;
            paint.setTextSize(size);
        } else {
            return size - step;
        }
    }
}

It's simple, I increase the text size until the text rect bound dimensions are close enough to maxWidth and maxHeight, to decrease the loop repeats just change step to a bigger value (accuracy vs speed), Maybe it's not the best way to achieve this but It works.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBadalView Question on Stackoverflow
Solution 1 - JavaMichael ScheperView Answer on Stackoverflow
Solution 2 - JavaslyblotyView Answer on Stackoverflow
Solution 3 - JavaFarshad TahmasbiView Answer on Stackoverflow