Jak uzyskać szerokość ciągu na Androidzie?

Odpowiedzi:

203

Możesz użyć getTextBounds(String text, int start, int end, Rect bounds)metody obiektu Paint. Możesz użyć obiektu malowania dostarczonego przez a TextViewlub zbudować go samodzielnie z pożądanym wyglądem tekstu.

Korzystając z widoku tekstowego, możesz wykonać następujące czynności:

Rect bounds = new Rect();
Paint textPaint = textView.getPaint();
textPaint.getTextBounds(text, 0, text.length(), bounds);
int height = bounds.height();
int width = bounds.width();
Szczery
źródło
5
@Frank: A co, jeśli łańcuch jest ciągiem łączonym?
Ashwin
Świetna odpowiedź. Nawiasem mówiąc, wynik będzie dokładniejszy, jeśli zadzwonisz textView.setTextSize().
li2
19

Istnieją dwie różne miary szerokości tekstu. Jedna to liczba pikseli, które zostały narysowane na szerokość, druga to liczba „pikseli”, które należy przesunąć kursor po narysowaniu tekstu.

paint.measureText i paint.getTextWidths zwracają liczbę pikseli (w liczbie zmiennoprzecinkowej), o którą kursor powinien zostać przesunięty po narysowaniu danego ciągu. Aby określić liczbę pomalowanych pikseli, użyj funkcji paint.getTextBounds, jak wspomniano w innej odpowiedzi. Uważam, że nazywa się to „Advance” czcionki.

W przypadku niektórych czcionek te dwa wymiary różnią się (bardzo), na przykład czcionka Black Chancery ma litery, które wykraczają poza inne litery (nakładają się) - patrz duże „L”. Użyj paint.getTextBounds, jak wspomniano w innej odpowiedzi, aby pomalować piksele.

arberg
źródło
6

Zmierzyłem szerokość w ten sposób:

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

To by ci pomogło.

Hiren Patel
źródło
3

Najprawdopodobniej chcesz poznać pomalowane wymiary dla danego ciągu tekstu z określoną czcionką (tj. Konkretną Typeface rodziną czcionek „sans-serif” ze stylem BOLD_ITALIC i określonym rozmiarem w sp lub px).

Zamiast nadmuchać pełnowymiarowy TextView, możesz zejść niżej i pracować z Paintobiektem bezpośrednio dla tekstu jednowierszowego , na przykład:

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



W przypadku tekstu wielowierszowego lub łączonego ( SpannedString) rozważ użycie znaku StaticLayout, w którym podajesz szerokość i uzyskujesz wysokość. Aby uzyskać bardzo szczegółową odpowiedź na temat mierzenia i rysowania tekstu na płótnie w niestandardowym widoku, patrz: https://stackoverflow.com/a/41779935/954643

Warto również zwrócić uwagę na poniższą odpowiedź @ arberga na temat pomalowanych pikseli w porównaniu z szerokością wyprzedzenia ("liczba pikseli (w liczbie zmiennoprzecinkowej), o którą kursor powinien zostać przesunięty po narysowaniu danego ciągu"), na wypadek gdybyś musiał sobie z tym poradzić.

qix
źródło
2

Chciałbym podzielić się lepszym (bardziej wszechstronnym niż obecnie akceptowana odpowiedź) sposobem uzyskania dokładnej szerokości rysowanego tekstu ( String) przy użyciu klasy statycznej StaticLayout:

StaticLayout.getDesiredWidth(text, textPaint))

ta metoda jest dokładniejsza niż textView.getTextBounds(), ponieważ można obliczyć szerokość pojedynczej linii w multilinii TextViewlub nie używać jej TextViewna początku (na przykład w niestandardowej Viewimplementacji).

Ten sposób jest podobny textPaint.measureText(text), jednak w rzadkich przypadkach wydaje się być dokładniejszy.

Serj Ardovic
źródło