Андроид холст drawText установить размер шрифта от ширины?

Я хочу нарисовать текст на canvas определенной ширины, используя .drawtext

Например, ширина текста всегда должна быть 400px независимо от того, что представляет собой входной текст.

Если входной текст длиннее, он уменьшит размер шрифта, если текст ввода короче, он соответственно увеличит размер шрифта.

Ответ 1

Здесь гораздо более эффективный метод:

/**
 * 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);
}

Затем все, что вам нужно сделать, это setTextSizeForWidth(paint, 400, str); (400 - это ширина примера в вопросе).

Для еще большей эффективности вы можете сделать Rect статическим членом класса, сохраняя его от экземпляра каждый раз. Однако это может привести к проблемам concurrency и, возможно, будет препятствовать ясности кода.

Ответ 2

Попробуйте следующее:

/**
 * 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()

Ответ 3

Решение Michael Scheper кажется приятным, но для меня это не сработало, мне нужно было получить самый большой размер текста, который можно сделать на мой взгляд, но этот подход зависит от первого установленного размера текста. Каждый раз, когда вы устанавливаете другой размер, вы получите разные результаты, которые не могут сказать, что это правильный ответ в любой ситуации.

Итак, я попробовал другой способ:

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;
        }
    }
}

Это просто, я увеличиваю размер текста до тех пор, пока размер прямоугольника, связанного с текстом, не станет достаточно близко к maxWidth и maxHeight, чтобы уменьшить повторяющиеся петли, просто измените step на большее значение (точность против скорости), возможно это не лучший способ достичь этого, но он работает.