Reputation: 13517
I have a a textview which as width as fill_parent
under the root layout which means it has the width of the screen which is 480
.
I am trying to measure the bounds of this text in the text view. So I did this :
Rect rect = new Rect();
textView.getPaint().getTextBounds(text,0,text.length()-1,rect);
Log.v(TAG,"Width : Height ="+rect.width()+" : "+width.height());
But it prints 10278 : 79
. Why is it printing the width as 10278 when the scren width itself is 480
? If it is assuming it to be a single line and calculating then what is the point of having getTextBounds
.
Upvotes: 1
Views: 1868
Reputation: 1274
The documentation states that int end is "1 past the last char in the string to measure." http://developer.android.com/reference/android/graphics/Paint.html#getTextBounds(java.lang.String, int, int, android.graphics.Rect)
You should have:
textView.getPaint().getTextBounds(text, 0, text.length(), rect);
This also applies to Canvas.drawText().
The TextView displaying text would be "wrapping" the text. The method getTextBounds is not aware of the TextView at all.
In fact, if you were to build your own custom View for displaying text, getTextBounds would be very useful for achieving your own text wrapping. The following code does a terrible job of presentation, but iterates over a String, drawing sections of it to a Canvas, effectively wrapping the text.
private void drawText(Canvas canvas) {
String text = "Nunc eleifend erat eu nulla varius iaculis. Quisque feugiat justo sit amet" +
" neque interdum tempor. Curabitur faucibus facilisis tristique. Donec posuere" +
" viverra magna, eu accumsan sapien congue id. Cras fringilla justo ut lacus" +
" molestie, et venenatis orci egestas. Vivamus pretium, nisl quis cursus cursus," +
" dolor eros porta neque, sit amet viverra ante orci non elit. Donec odio neque," +
" volutpat sit amet dui sit amet, fringilla tempus sapien. Donec sed mollis justo." +
" In dignissim tincidunt neque, eu luctus justo egestas nec. Donec commodo ut arcu" +
" vel placerat. Donec ullamcorper justo eget justo commodo hendrerit. Quisque" +
" commodo imperdiet posuere. Aenean vehicula dui.";
Paint paint = new Paint();
paint.setTextSize(30);
paint.setAntiAlias(true);
int padding = 20;
int availWidth = getWidth() - 2 * padding;
int availHeight = getHeight() - 2 * padding;
Rect bounds = new Rect();
int currentTextBottom = 0;
int firstCharInLine = 0;
int lastCharInLine = 0;
outerLoop: while (currentTextBottom < availHeight) {
while (Character.isWhitespace(text.charAt(firstCharInLine))) {
lastCharInLine = ++firstCharInLine;
}
for (int i = firstCharInLine + 1; i < text.length(); i++) {
paint.getTextBounds(text, firstCharInLine, i, bounds);
if (bounds.width() <= availWidth) {
if (Character.isWhitespace(text.charAt(i))) {
lastCharInLine = i;
}
} else {
currentTextBottom += bounds.height();
if (firstCharInLine == lastCharInLine) {
lastCharInLine = i;
}
canvas.drawText(text, firstCharInLine, lastCharInLine, padding, currentTextBottom + padding, paint);
firstCharInLine = lastCharInLine++;
break;
}
if (i == text.length() - 1) {
currentTextBottom += bounds.height();
lastCharInLine = text.length();
canvas.drawText(text, firstCharInLine, lastCharInLine, padding, currentTextBottom + padding, paint);
break outerLoop;
}
}
}
}
}
EDIT - as a side note, I've just now noticed a difference between bounds.width() and Paint.measureText()! Totally unrelated to the above code, I was having issues with Paint.Align.Center glitching and not always working as expected. So I removed any text alignment and tried:
canvas.drawText(
text,
viewWidth / 2f - bounds.width() / 2f,
viewHeight / 2f + bounds.height() / 2f,
paint);
But this doesn't align horizontally properly. When I did this instead:
float textWidth = paint.measureText(text);
canvas.drawText(
text,
viewWidth / 2f - textWidth / 2,
viewHeight / 2f + bounds.height() / 2f,
paint);
It aligned to my satisfaction :)
Upvotes: 2
Reputation: 1074
The getTextBounds does not return the size of the View, but the minimal space required to display the full string that you give to it:
Return in bounds (allocated by the caller) the smallest rectangle that encloses all of the characters, with an implied origin at (0,0).
This means that for your 1000 characters, and given the currently configured font in the Paint
object, it will require at least 10278 pixels to print them. It does not matter that your text or the Paint
object came from the textView.
Upvotes: 1