2010-02-25 7 views
18

J'ai un contrôle personnalisé qui fait beaucoup de dessin 2D directement au canvas.Enveloppant texte long sur un canevas Android

Certains de ces dessins sont du texte, donc j'utilise la méthode Canvas.drawText().

Je souhaite dessiner le texte dans certaines limites - une partie supérieure gauche, une certaine largeur maximale et un nombre maximal de lignes. Après avoir dessiné le texte, je veux savoir combien de lignes cela a pris.

Y a-t-il une fonction intégrée pour dessiner du texte dans les limites en faisant le fractionnement judicieusement?

Sinon, existe-t-il une recette standard pour cela?

+0

Voir cette réponse pour un bon exemple d'utilisation de 'StaticLayout's: http://stackoverflow.com/a/8369690/293280 –

Répondre

30

Vous pouvez utiliser la classe android.text.StaticLayout pour cela; Créez simplement StaticLayout pour le texte, l'alignement, la largeur, etc. souhaités et appelez sa méthode draw(Canvas) pour dessiner sur le canevas.

+0

Incroyable que je l'avais négligé – Will

+0

Est-ce seulement pour Android? Qu'en est-il des autres plateformes? –

+0

Super! Comment centrez-vous le texte dans la toile? –

4

Vous pouvez utiliser Paint.getTextBounds() pour mesurer la taille de la chaîne entière ou Paint.getTextWidths() pour obtenir la largeur de chaque caractère. Ensuite, divisez la chaîne de manière appropriée avant de la dessiner.

3

J'ai eu le même problème. Une de mes premières solutions est la suivante.

/** 
    * This function draws the text on the canvas based on the x-, y-position. 
    * If it has to break it into lines it will do it based on the max width 
    * provided. 
    * 
    * @author Alessandro Giusa 
    * @version 0.1, 14.08.2015 
    * @param canvas 
    *   canvas to draw on 
    * @param paint 
    *   paint object 
    * @param x 
    *   x position to draw on canvas 
    * @param y 
    *   start y-position to draw the text. 
    * @param maxWidth 
    *   maximal width for break line calculation 
    * @param text 
    *   text to draw 
    */ 
public static void drawTextAndBreakLine(final Canvas canvas, final Paint paint, 
     final float x, final float y, final float maxWidth, final String text) { 
    String textToDisplay = text; 
    String tempText = ""; 
    char[] chars; 
    float textHeight = paint.descent() - paint.ascent(); 
    float lastY = y; 
    int nextPos = 0; 
    int lengthBeforeBreak = textToDisplay.length(); 
    do { 
     lengthBeforeBreak = textToDisplay.length(); 
     chars = textToDisplay.toCharArray(); 
     nextPos = paint.breakText(chars, 0, chars.length, maxWidth, null); 
     tempText = textToDisplay.substring(0, nextPos); 
     textToDisplay = textToDisplay.substring(nextPos, textToDisplay.length()); 
     canvas.drawText(tempText, x, lastY, paint); 
     lastY += textHeight; 
    } while(nextPos < lengthBeforeBreak); 
} 

Ce qui manque:

  • Aucun mécanisme de cassure intelligente, car elle se casse basée sur le maxWidth

Comment appeler? J'ai une classe statique appelée CanvasUtils où j'encapsule des trucs comme ça. Fondamentalement, je dessine le texte dans un rectangle. C'est la raison pour laquelle textHeight est la hauteur du texte. Mais vous pouvez transmettre ce que vous voulez à la fonction.

Bonne programmation!

+0

Oui ça a marché pour moi mais ça force les mots à casser! Y a-t-il moyen d'arranger ça? – Eenvincible

+0

Hey Eenvincible, vous voulez dire des mots simples? Césure? –

+0

Pas en particulier. Ce qui se passe avec ce code, c'est que le texte s'enroule correctement dans le rectangle, mais que certains mots sont coupés et se terminent par de nouvelles lignes avec une partie des mots sur une ligne et une partie sur la ligne suivante. – Eenvincible