Wie bekomme ich die Stringbreite auf Android?

104

Ich würde gerne auch Höhe bekommen, wenn möglich.

Mikael Lindlöf
quelle

Antworten:

201

Sie können die getTextBounds(String text, int start, int end, Rect bounds)Methode eines Paint-Objekts verwenden. Sie können entweder das von a gelieferte Malobjekt verwenden TextViewoder selbst eines mit dem gewünschten Textauftritt erstellen.

Mit einer Textansicht können Sie Folgendes tun:

Rect bounds = new Rect();
Paint textPaint = textView.getPaint();
textPaint.getTextBounds(text, 0, text.length(), bounds);
int height = bounds.height();
int width = bounds.width();
Frank
quelle
5
@Frank: Was ist, wenn der String ein übergreifender String ist?
Ashwin
Gute Antwort. Das Ergebnis ist übrigens genauer, wenn Sie anrufen textView.setTextSize().
Li2
81

Wenn Sie nur die Breite benötigen, können Sie verwenden:

float width = paint.measureText(string);

http://developer.android.com/reference/android/graphics/Paint.html#measureText(java.lang.String)

SharkAlley
quelle
4
Wenn Sie den Text mit einer bestimmten Schriftgröße messen möchten, können Sie ihn außerdem verwenden TextPaint paint = new TextPaint(); paint.setTextSize(textSize);. textSizeist in Pixel.
Nathan Reline
Und um Höhe zu bekommen?
Prinz
19

Es gibt zwei verschiedene Breitenmaße für einen Text. Eines ist die Anzahl der Pixel, die in der Breite gezeichnet wurden, das andere ist die Anzahl der 'Pixel', die der Cursor nach dem Zeichnen des Textes nach vorne bewegen sollte.

paint.measureText und paint.getTextWidths geben die Anzahl der Pixel (in float) zurück, die der Cursor nach dem Zeichnen der angegebenen Zeichenfolge vorrücken soll. Verwenden Sie für die Anzahl der gemalten Pixel paint.getTextBounds, wie in der anderen Antwort angegeben. Ich glaube, dies wird als "Fortschritt" der Schrift bezeichnet.

Bei einigen Schriftarten unterscheiden sich diese beiden Maße (stark), z. B. hat die Schriftart Black Chancery Buchstaben, die sich über die anderen Buchstaben hinaus erstrecken (überlappend) - siehe Großbuchstabe 'L'. Verwenden Sie paint.getTextBounds wie in einer anderen Antwort erwähnt, um Pixel zu malen.

Arberg
quelle
6

Ich habe die Breite folgendermaßen gemessen:

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());

Das würde dir helfen.

Hiren Patel
quelle
3

Höchstwahrscheinlich möchten Sie die gemalten Abmessungen für eine bestimmte Textzeichenfolge mit einer bestimmten Schriftart kennen (dh eine bestimmte Schriftart Typefacewie die serifenlose Schriftfamilie mit einem BOLD_ITALIC-Stil und eine bestimmte Größe in sp oder px).

Anstatt einen ausgewachsenen Text aufzublasen TextView, können Sie auf einer niedrigeren Ebene Paintdirekt mit einem Objekt für einzeiligen Text arbeiten, zum Beispiel:

// 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());

Verwenden Sie 

für mehrzeiligen oder überspannten Text ( SpannedString) die Verwendung von a StaticLayout, in der Sie die Breite angeben und die Höhe ableiten. Eine sehr ausführliche Antwort zum Messen und Zeichnen von Text auf einer Leinwand in einer benutzerdefinierten Ansicht finden Sie unter: https://stackoverflow.com/a/41779935/954643

Erwähnenswert ist auch die Antwort von @ arberg unten zu den gemalten Pixeln im Vergleich zur Vorschubbreite ("Anzahl der Pixel (in Gleitkomma), um die der Cursor nach dem Zeichnen der angegebenen Zeichenfolge vorgeschoben werden soll"), falls Sie sich damit befassen müssen.

qix
quelle
2

Ich möchte einen besseren Weg (vielseitiger als die derzeit akzeptierte AntwortString ) mit der Verwendung der statischen Klasse teilen , um die genaue Breite eines gezeichneten Textes ( ) zu erhalten StaticLayout:

StaticLayout.getDesiredWidth(text, textPaint))

Diese Methode ist genauer als textView.getTextBounds(), da Sie die Breite einer einzelnen Zeile in einer mehrzeiligen Zeile berechnen können TextViewoder sie möglicherweise nicht verwenden TextView(z. B. in einer benutzerdefinierten ViewImplementierung).

Dieser Weg ist ähnlich textPaint.measureText(text), scheint jedoch in seltenen Fällen genauer zu sein.

Serj Ardovic
quelle