2010-02-25 20 views
18

Tengo un control personalizado que está haciendo un montón de dibujo 2D directamente al canvas.Envoltura larga de texto en un lienzo de Android

Parte de este dibujo es texto, entonces estoy usando el método Canvas.drawText().

Quiero dibujar el texto dentro de algunos límites: un ancho máximo superior izquierdo, cierto y un número máximo de líneas. Después de dibujar el texto, quiero saber cuántas líneas tomó.

¿Hay una función incorporada para dibujar texto dentro de los límites haciendo la división de manera sensata?

Si no, ¿existe una receta estándar para hacerlo?

+0

Vea esta respuesta para un buen ejemplo de uso de 'StaticLayout's: http://stackoverflow.com/a/8369690/293280 –

Respuesta

30

Puede usar la clase android.text.StaticLayout para esto; simplemente cree un StaticLayout para el texto deseado, alineación, ancho, etc. y llame a su método draw(Canvas) para dibujar en el lienzo.

+0

Sorprendente que lo haya pasado por alto – Will

+0

¿Es esto solo para Android? ¿Qué hay de otras plataformas? –

+0

¡Genial! ¿Cómo centrarías el texto en el lienzo? –

4

Puede usar Paint.getTextBounds() para medir el tamaño de la cadena completa o Paint.getTextWidths() para obtener el ancho de cada carácter. Luego divida la cadena apropiadamente antes de dibujarla.

3

Tuve el mismo problema. Una de mi primera solución es seguir.

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

Lo que falta:

  • Sin mecanismo de ruptura de línea inteligente, ya que rompe basa en la anchoMax

Cómo llamar?

paint.setTextSize(40); 
    paint.setColor(Color.WHITE); 
    paint.setSubpixelText(true); 
    float textHeight = paint.descent() - paint.ascent(); 
    CanvasUtils.drawTextAndBreakLine(canvas, paint, this.left, 
      textHeight, this.displayWidth, this.text); 

Tengo una clase estática llamada CanvasUtils donde encapsulo cosas como esta. Básicamente dibujo el texto dentro de un rectángulo. Esta es la razón por la cual textHeight es la altura del texto. Pero puedes pasar lo que quieras a la función.

¡Buena programación!

+0

Sí, esto funcionó para mí, pero obliga a las palabras a romperse. ¿Hay alguna manera de arreglar eso? – Eenvincible

+0

Hola Eenvincible, ¿te refieres a palabras sueltas? ¿Separación? –

+0

No en particular. lo que sucede con este código es que el texto se ajusta correctamente dentro del rectángulo, pero algunas palabras se cortan y terminan rompiendo en nuevas líneas con parte de las palabras que aparecen en una línea y parte de ella en la línea siguiente. – Eenvincible

Cuestiones relacionadas