So, having spent the obligatory five hours trying to figure out how
android wanted me to do it (other than just "don't do that!"), I ended
up writing this bit of code to do what I actually WANTED.
It's not too bad except for the one section which needs to be made a
lot more efficient.
In case it helps anyone else, I post it here. I would still like to
hear about the 'right way' to do it.
public void drawTextInRect( Canvas canvas, Paint paint, Rect r,
CharSequence text ) {
// ok, I have to do it all myself, pity me!
// initial text range and starting position
int start = 0;
int end = text.length() - 1;
float x = r.left;
float y = r.top;
int allowedWidth = r.width(); // constrain text block within
this
width in pixels
if( allowedWidth < 30 ) {
return; // you have got to be kidding me! I can't
work with
this! You deserve worse!
}
// get the distance in pixels between two lines of text
int lineHeight = paint.getFontMetricsInt( null );
// emit one line at a time, as much as will fit, with word wrap
on
whitespace.
while( start < end ) {
int charactersRemaining = end - start +
1;
int charactersToRenderThisPass = charactersRemaining;
//
optimism!
int extraSkip = 0;
// This 'while' is nothing to be proud of.
// This should probably be a binary search or more
googling to
// find "character index at distance N pixels in string"
while( charactersToRenderThisPass > 0
&& paint.measureText(text, start, start
+charactersToRenderThisPass ) > allowedWidth ) {
// remaining text won't fit, cut one character
from the end and
check again
charactersToRenderThisPass--;
}
// charactersToRenderThisPass would definitely fit, but
could be in
the middle of a word
int thisManyWouldDefinitelyFit =
charactersToRenderThisPass;
if( charactersToRenderThisPass < charactersRemaining ) {
while( charactersToRenderThisPass > 0
&& !Character.isWhitespace(
text.charAt( start
+charactersToRenderThisPass-1) ) ) {
charactersToRenderThisPass--; // good
bye character that would
have fit!
}
}
// Now wouldn't it be nice to be able to put in line
breaks?
int i;
for( i=0; i<charactersToRenderThisPass; i++ ) {
if( text.charAt( start+i ) == '\n' ) { // um,
what's unicode for
'isLineBreak' or '\n'?
// cool, lets stop this line early
charactersToRenderThisPass = i;
extraSkip = 1; // so we don't start
next line with the lineBreak
character
break;
}
}
if( charactersToRenderThisPass < 1 && (extraSkip == 0))
{
// no spaces found, must be a really long word.
// Panic and show as much as would fit,
breaking the word in the
middle
charactersToRenderThisPass =
thisManyWouldDefinitelyFit;
}
// Emit this line of characters and advance our offsets
for the
next line
if( charactersToRenderThisPass > 0 ) {
canvas.drawText( text, start,
start+charactersToRenderThisPass, x,
y, paint );
}
start += charactersToRenderThisPass + extraSkip;
y += lineHeight;
// start had better advance each time through the
while, or we've
invented an infinite loop
if( (charactersToRenderThisPass + extraSkip) < 1 ) {
return; // better than freezing, I guess. I am
a coward.
}
}
// write google a letter asking why I couldn't find this as an
existing function
// after doing a LOT of googling. Is my phone going to explode?
}
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en