2012-06-01 14 views
13

Estoy tratando de calcular el ancho de un párrafo de texto de líneas múltiples. Que yo sepa, la única clase que puede hacer esto en Android es la clase StaticLayout (o DynamicLayout). Al usar esta clase, no obtengo la longitud adecuada de mi fragmento de texto, sino que las dimensiones medidas son a veces más pequeñas y, a veces, mayores según el tamaño del texto.¿Cómo determinar confiablemente el ancho de una cadena de varias líneas?

Así que, básicamente, estoy buscando una manera de medir de manera confiable el ancho de una cadena de texto de varias líneas.

La siguiente imagen muestra cómo el ancho medido difiere de la longitud del texto real en varios tamaños de texto. Diverging text and measure

La captura de pantalla se crea ejecutando el código siguiente en una vista personalizada:

@Override 
protected void onDraw(Canvas canvas) { 
    for(int i = 0; i < 15; i++) { 
    int startSize = 10; 
    int curSize = i + startSize; 
    paint.setTextSize(curSize); 
    String text = i + startSize + " - " + TEXT_SNIPPET; 
    layout = new StaticLayout(text, 
           paint, 
           Integer.MAX_VALUE, 
           Alignment.ALIGN_NORMAL, 
           1.0f, 
           0.0f, 
           true); 

    float top = STEP_DISTANCE * i; 
    float measuredWidth = layout.getLineMax(0); 
    canvas.drawRect(0, top, measuredWidth, top + curSize, bgPaint); 
    canvas.drawText(text, 0, STEP_DISTANCE * i + curSize, paint); 
    } 
} 
+2

¿Has probado 'Paint.measureText()'? – neevek

+0

http://stackoverflow.com/questions/7549182/android-paint-measuretext-vs-gettextbounds – nullpotent

+0

@Neevek produce el mismo resultado, pero en la parte superior no es capaz de medir texto de varias líneas. – Moritz

Respuesta

1

Usted podría tratar de usar límites de texto a conseguir.

private int calculateWidthFromFontSize(String testString, int currentSize) 
{ 
    Rect bounds = new Rect(); 
    Paint paint = new Paint(); 
    paint.setTextSize(currentSize); 
    paint.getTextBounds(testString, 0, testString.length(), bounds); 

    return (int) Math.ceil(bounds.width()); 
} 

private int calculateHeightFromFontSize(String testString, int currentSize) 
{ 
    Rect bounds = new Rect(); 
    Paint paint = new Paint(); 
    paint.setTextSize(currentSize); 
    paint.getTextBounds(testString, 0, testString.length(), bounds); 

    return (int) Math.ceil(bounds.height()); 
} 
1

tuve un problema similar en el que el ancho de texto medido fue apagado por un poco, una vez que se establece un tipo de letra de la pintura esto desaparecerá. Así que antes de utilizar el objeto paint en el StaticLayout acaba de establecer el tipo de letra:

textPaint.setTypeface(Typeface.create("sans-serif", Typeface.NORMAL)) 

o cualquier tipo de letra que desea.

0

Aquí hay una manera en la que puede obtener el ancho de varias líneas de cualquier longitud de texto. usableButtonWidth puede ser un espacio de texto dado. Usé usableButtonWidth = ancho del botón - relleno. Pero se puede usar cualquier valor predeterminado.

Usando StaticLayout, puede obtener el alto del texto para usableButtonWidth. Luego, trato de reducir el ancho disponible disminuyéndolo 1px en un bucle. Si la altura aumenta, llegamos a saber que el ancho utilizado anteriormente era el máximo permitido.

Devuelve este valor como el ancho del texto de varias líneas.

private int getTextWidth(){ 
    if(this.getText().length() != 0){ 
     Paint textPaint = new Paint(); 
     Rect bounds = new Rect(); 
     textPaint.setTextSize(this.getTextSize()); 
     if(mTypeface != null){ 
      textPaint.setTypeface(mTypeface); 
     } 
     String buttonText = this.getText().toString(); 
     textPaint.getTextBounds(buttonText, 0, buttonText.length(), bounds); 

     if(bounds.width() > usableButtonWidth){ 
      TextPaint longTextPaint = new TextPaint(); 
      longTextPaint.setTextSize(this.getTextSize()); 
      if(mTypeface != null){ 
       longTextPaint.setTypeface(mTypeface); 
      } 
      StaticLayout staticLayout = new StaticLayout(this.getText(), longTextPaint, usableButtonWidth, 
        Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); 
      int textLineCount = (int)Math.ceil(staticLayout.getHeight()/bounds.height()); 
      int multiLineTextWidth = usableButtonWidth; 
      while ((int)Math.ceil(staticLayout.getHeight()/bounds.height()) == textLineCount && multiLineTextWidth > 1){ 
       multiLineTextWidth--; 
       staticLayout = new StaticLayout(this.getText(), longTextPaint, multiLineTextWidth, 
         Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); 
      } 
      return multiLineTextWidth+1; 
     } else { 
      return bounds.width(); 
     } 
    } else { 
     return 0; 
    } 
} 
Cuestiones relacionadas