在Android Canvas上换行长文本

23

我有一个自定义控件,需要直接在canvas上进行大量的2D绘图操作。

其中一些是文本内容,因此我使用了Canvas.drawText()方法。

我想要将文本绘制在某个范围内 - 左上角,最大宽度和最大行数。 在绘制文本之后,我想知道它占用了多少行。

是否有内置函数可以在给定范围内绘制文本并合理地拆分?

如果没有,是否有标准的方法可以实现这个功能?


请参考以下链接,了解如何使用StaticLayout:https://dev59.com/Omw15IYBdhLWcg3wMpEY#8369690 - Joshua Pinter
3个回答

35
您可以使用android.text.StaticLayout类来实现此功能;只需为所需的文本、对齐方式、宽度等创建一个StaticLayout,并调用其draw(Canvas)方法即可在画布上绘制。

太惊人了,我竟然忽略了它。 - Will
这只是针对Android吗?其他平台呢? - B Seven
太好了!您如何将文本居中显示在画布上? - Tim Kist
@zboarda 不太明白你的意思,不过你试过 Paint.setTextAlign(Align.CENTER); 吗? - Ray Britton
@Eenvincible 请查看我的博客文章 http://www.skoumal.net/en/android-drawing-multiline-text-on-bitmap/ - gingo

4
您可以使用Paint.getTextBounds()来测量整个字符串的大小,或使用Paint.getTextWidths()获取每个字符的宽度。然后在绘制之前适当地拆分字符串。

4
我有同样的问题。我最初的解决方案如下。
/**
     * This function draws the text on the canvas based on the x-, y-position.
     * If it has to break it into lines it will do it based on the max width
     * provided.
     * 
     * @author Alessandro Giusa
     * @version 0.1, 14.08.2015
     * @param canvas
     *            canvas to draw on
     * @param paint
     *            paint object
     * @param x
     *            x position to draw on canvas
     * @param y
     *            start y-position to draw the text.
     * @param maxWidth
     *            maximal width for break line calculation
     * @param text
     *            text to draw
     */
public static void drawTextAndBreakLine(final Canvas canvas, final Paint paint,
        final float x, final float y, final float maxWidth, final String text) {
    String textToDisplay = text;
    String tempText = "";
    char[] chars;
    float textHeight = paint.descent() - paint.ascent();
    float lastY = y;
    int nextPos = 0;
    int lengthBeforeBreak = textToDisplay.length();
    do {
        lengthBeforeBreak = textToDisplay.length();
        chars = textToDisplay.toCharArray();
        nextPos = paint.breakText(chars, 0, chars.length, maxWidth, null);
        tempText = textToDisplay.substring(0, nextPos);
        textToDisplay = textToDisplay.substring(nextPos, textToDisplay.length());
        canvas.drawText(tempText, x, lastY, paint);
        lastY += textHeight;
    } while(nextPos < lengthBeforeBreak);
}

缺少什么:

  • 没有智能断行机制,因为它是基于最大宽度进行断行的

如何调用?

    paint.setTextSize(40);
    paint.setColor(Color.WHITE);
    paint.setSubpixelText(true);
    float textHeight = paint.descent() - paint.ascent();
    CanvasUtils.drawTextAndBreakLine(canvas, paint, this.left,
            textHeight, this.displayWidth, this.text);

我有个名叫 CanvasUtils 的静态类,里面封装了像这样的内容。基本上,我在一个矩形内绘制文本。这就是为什么 textHeight 是文本的高度的原因。但你可以把想要的东西传递给函数。
良好的编程!

是的,这对我有用,但它会强制换行!有没有办法解决这个问题? - Eenvincible
嘿,Eenvincible,你是指单个单词吗?连字符? - Alessandro Giusa
没有特别的。这段代码的情况是,文本正确地在矩形内换行,但有些单词会被切断,最终分成新的行,在一行中显示部分单词,在下一行中显示其余部分。 - Eenvincible
这就是我所说的。您想要一个能够正确断字的算法,还是只是将受影响的单词放到下一行的算法? - Alessandro Giusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接