¿Cómo obtener el ancho de la cadena en Android?

Respuestas:

202

Puede utilizar el getTextBounds(String text, int start, int end, Rect bounds)método de un objeto Paint. Puede utilizar el objeto de pintura proporcionado por unTextView o construir uno usted mismo con la apariencia de texto deseada.

Con una vista de texto, puede hacer lo siguiente:

Rect bounds = new Rect();
Paint textPaint = textView.getPaint();
textPaint.getTextBounds(text, 0, text.length(), bounds);
int height = bounds.height();
int width = bounds.width();
Franco
fuente
5
@Frank: ¿Qué pasa si la cadena es una cadena extendida?
Ashwin
Gran respuesta. Por cierto, el resultado será más preciso si llama textView.setTextSize().
li2
19

Hay dos medidas de ancho diferentes para un texto. Uno es el número de píxeles que se ha dibujado en el ancho, el otro es el número de 'píxeles' que debe avanzar el cursor después de dibujar el texto.

paint.measureText y paint.getTextWidths devuelven el número de píxeles (en flotante) que el cursor debe avanzar después de dibujar la cadena dada. Para la cantidad de píxeles pintados, use paint.getTextBounds como se menciona en otra respuesta. Creo que esto se llama el "avance" de la fuente.

Para algunas fuentes, estas dos medidas difieren (mucho), por ejemplo, la fuente Black Chancery tiene letras que se extienden más allá de las otras letras (superpuestas); consulte la 'L' mayúscula. Use paint.getTextBounds como se menciona en otra respuesta para pintar píxeles.

Arberg
fuente
6

He medido el ancho de esta manera:

String str ="Hiren Patel";

Paint paint = new Paint();
paint.setTextSize(20);
Typeface typeface = Typeface.createFromAsset(getAssets(), "Helvetica.ttf");
paint.setTypeface(typeface);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
Rect result = new Rect();
paint.getTextBounds(str, 0, str.length(), result);

Log.i("Text dimensions", "Width: "+result.width());

Esto te ayudaría.

Hiren Patel
fuente
3

Lo más probable es que desee conocer las dimensiones pintadas para una determinada cadena de texto con una fuente determinada (es decir, una Typefacefamilia de fuentes en particular como la "sans-serif" con un estilo BOLD_ITALIC y un tamaño particular en sp o px).

En lugar de inflar un texto completo TextView, puede bajar de nivel y trabajar con un Paintobjeto directamente para texto de una sola línea , por ejemplo:

// Maybe you want to construct a (possibly static) member for repeated computations
Paint paint = new Paint();

// You can load a font family from an asset, and then pick a specific style:
//Typeface plain = Typeface.createFromAsset(assetManager, pathToFont); 
//Typeface bold = Typeface.create(plain, Typeface.DEFAULT_BOLD);
// Or just reference a system font:
paint.setTypeface(Typeface.create("sans-serif",Typeface.BOLD));

// Don't forget to specify your target font size. You can load from a resource:
//float scaledSizeInPixels = context.getResources().getDimensionPixelSize(R.dimen.mediumFontSize);
// Or just compute it fully in code:
int spSize = 18;
float scaledSizeInPixels = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP,
            spSize,
            context.getResources().getDisplayMetrics());
paint.setTextSize(scaledSizeInPixels);

// Now compute!
Rect bounds = new Rect();
String myString = "Some string to measure";
paint.getTextBounds(myString, 0, myString.length(), bounds);
Log.d(TAG, "width: " + bounds.width() + " height: " + bounds.height());



Para texto de varias líneas o extendido ( SpannedString), considere usar a StaticLayout, en el que proporciona el ancho y deriva la altura. Para obtener una respuesta muy elaborada sobre cómo medir y dibujar texto en un lienzo en una vista personalizada haciendo eso, consulte: https://stackoverflow.com/a/41779935/954643

También vale la pena señalar la respuesta de @arberg a continuación sobre los píxeles pintados frente al ancho de avance ("número de píxeles (en flotante) que el cursor debe avanzar después de dibujar la cadena dada"), en caso de que necesite lidiar con eso.

qix
fuente
2

Me gustaría compartir una mejor manera (más versátil que la respuesta aceptada actual) de obtener el ancho exacto de un texto dibujado ( String) con el uso de la clase estática StaticLayout:

StaticLayout.getDesiredWidth(text, textPaint))

este método es más preciso que textView.getTextBounds(), ya que puede calcular el ancho de una sola línea en una línea múltiple TextView, o puede que no lo utilice TextViewpara empezar (por ejemplo, en una Viewimplementación personalizada ).

Esta forma es similar a textPaint.measureText(text), sin embargo, parece ser más precisa en casos raros.

Serj Ardovic
fuente