web-dev-qa-db-fra.com

android canvas drawText définit la taille de la police à partir de la largeur?

Je veux dessiner du texte sur canvas d'une certaine largeur en utilisant .drawtext

Par exemple, la largeur du texte doit toujours être 400px quel que soit le texte saisi.

Si le texte saisi est plus long, la taille de la police diminuera. Si le texte saisi est plus court, il augmentera la taille de la police en conséquence.

48
Badal

Voici une méthode beaucoup plus efficace:

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

Ensuite, tout ce que vous devez faire est setTextSizeForWidth(Paint, 400, str); (400 étant la largeur d'exemple dans la question).

Pour une efficacité encore plus grande, vous pouvez faire de Rect un membre de classe statique, en l'en empêchant d'être instancié à chaque fois. Cependant, cela peut introduire des problèmes de concurrence et entraverait sans doute la clarté du code.

100
Michael Scheper

Essaye ça:

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

la solution de Michael Scheper semble bien mais cela n'a pas fonctionné pour moi, j'avais besoin d'obtenir la plus grande taille de texte possible pour dessiner à mon avis mais cette approche dépend de la première taille de texte que vous avez définie, chaque chaque fois que vous définissez une taille différente, vous obtiendrez des résultats différents qui ne peuvent pas dire que c'est la bonne réponse dans chaque situation.

J'ai donc essayé une autre façon:

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

C'est simple, j'augmente la taille du texte jusqu'à ce que les dimensions du texte rect liées soient assez proches de maxWidth et maxHeight, pour diminuer les répétitions de boucle, il suffit de changer step en une valeur plus grande ( précision vs vitesse ), ce n'est peut-être pas la meilleure façon d'y parvenir mais ça marche.

2
Farshad Tahmasbi