Reputation: 18583
I want to calculate how many lines some text needs to fit into a fixed-width TextView
. And I used Paint.breakText
for this:
int maxWidth = WIDTH_IN_PIXELS;
int index = 0;
int linecnt = 0;
while (true) {
float[] measuredWidth = new float[1];
int advances = labelView.getPaint().breakText(text, index, text.length(), true, maxWidth, measuredWidth);
linecnt += 1;
index += advances;
if(index>=desc.length()) break;
}
However, the calculated linecnt
is always one less than what is really needed. After further investigation I find the API breaks text at arbitrary points within words, but when TextView layout text, it never breaks a word:
// textBreak:
Hello Wo
rld
// Real layout:
Hello
World
How do I get breakText to respect word wrapping? Or is there any other way to do this right?
p.s. I know I can always move back to the beginning of word within the loop, but that looks hacky and doesn't apply to every language. I am sure Android has some elegant way to do this, but I don't know the API/Flag to use.
p.p.s Sometimes TextView uses dash (-) to break a long word across lines, the rules for this is unclear.
Upvotes: 2
Views: 256
Reputation: 3258
This feels a little bit hacky, and it doesn't do the automatic word break in the middle with dashes, but the idea is I have a string of word break chars and just iterate backwards until I hit a break char. If the word is super long and there's no break char, just break at the end of the line.
var wordCharsToFit = labelView.getPaint().breakText(text, index, text.length(), true, maxWidth, measuredWidth);
while (wordCharsToFit > 0 && (
lyrics.length > wordCharsToFit && !"‐–〜゠= \t\r\n".contains(lyrics[wordCharsToFit]) ||
chords.length > wordCharsToFit && !"‐–〜゠= \t\r\n".contains(chords[wordCharsToFit])
)) {
wordCharsToFit -= 1
if (wordCharsToFit == 0) {
wordCharsToFit = totalCharsToFit
break
}
}
Upvotes: 0