2

我想计算一些文本需要多少行才能放入 fixed-width TextView。我用Paint.breakText这个:

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;           
}

然而,计算出来linecnt的总是比实际需要的少一。经过进一步调查,我发现 API 在单词中的任意点中断文本,但是当 TextView 布局文本时,它永远不会中断一个单词:

// textBreak:
Hello Wo
rld
// Real layout:
Hello
World

如何让 breakText 尊重自动换行?或者还有其他方法可以做到这一点吗?

ps 我知道我总是可以在循环中回到单词的开头,但这看起来很老套,并不适用于每种语言。我确信 Android 有一些优雅的方法可以做到这一点,但我不知道要使用的 API/标志。

pps 有时 TextView 使用破折号 (-) 将一个长单词换行,这个规则不清楚。

4

1 回答 1

0

这感觉有点 hacky,它不会在中间用破折号自动断字,但我的想法是我有一串断字字符,然后向后迭代,直到我碰到一个断字符。如果单词超长并且没有中断字符,则在行尾中断。

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
    }
}
于 2020-03-28T22:10:26.210 回答