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 :)