Canvas.drawText(...)无法打印换行

7
我尝试在创建的SurfaceView上写一些文本。如果没有标题并且文本中没有添加换行符,则可以正常工作。但是,如果我添加了标题并因此添加了换行符,则换行符不会像预期的那样打印出来,而是打印出这个符号[]。
有什么提示吗?
@Override
public void drawObject() {
String text = "";
if (title) {
   text = getGameBoard().getGame().getForeignProfile().getName() + "\n";
}
text = text + getScoreAsString();
getGameBoard().getCanvas().drawText(text, 0, text.length(), getPosition().getX(), getPosition().getY(), getPaint());
}

请查看我的答案:https://dev59.com/Omw15IYBdhLWcg3wMpEY#63098776 - Leo DroidCoder
5个回答

27
您可以尝试类似以下的方法来绘制带有换行符的文本:
Rect bounds = new Rect();
void drawString(Canvas canvas, Paint paint, String str, int x, int y) {
    String[] lines = str.split("\n");

    int yoff = 0;
    for (int i = 0; i < lines.length; ++i) {
        canvas.drawText(lines[i], x, y + yoff, paint);
        paint.getTextBounds(lines[i], 0, lines[i].length(), bounds);
        yoff += bounds.height();
    }
}

11

迪的回答很棒。以下代码基于迪的答案,但根据个人偏好进行了一些修改:

  1. 将其称为drawMultilineText(因为它有点类似于drawText)
  2. 按照drawText的顺序放置参数(文本,x,y,paint和canvas在最后)
  3. 在开始时获取行高度,因为bounds返回的高度取决于字母的高度,即e不像E那么高
  4. 在行之间添加20%的高度间隙

void drawMultilineText(String str, int x, int y, Paint paint, Canvas canvas) {
    int      lineHeight = 0;
    int      yoffset    = 0;
    String[] lines      = str.split("\n");

    // set height of each line (height of text + 20%)
    paint.getTextBounds("Ig", 0, 2, mBounds);
    lineHeight = (int) ((float) mBounds.height() * 1.2);
    // draw each line
    for (int i = 0; i < lines.length; ++i) {
        canvas.drawText(lines[i], x, y + yoffset, paint);
        yoffset = yoffset + lineHeight;
    }
}

神奇!!感谢@dee,救了我的一天。 - Billyjoker
太棒了,省去了我很多麻烦。 - Jitendra Surve
请问您能定义一下mBounds吗? - user19729496

4

继续改进Dee和FrinkTheBrave的答案。我添加了一个Rect参数到方法中,可以让你在特定宽度范围内进行绘制。我会考虑修改它以选择合适的字体大小,并确保它适合正确的高度区域。

这将允许您指定要写入的行的宽度,非常有用,可以将未格式化的文本字符串分成相似长度的行,并将它们绘制到画布上。

    private void drawMultilineText(String str, int x, int y, Paint paint, Canvas canvas, int fontSize, Rect drawSpace) {
    int      lineHeight = 0;
    int      yoffset    = 0;
    String[] lines      = str.split(" ");

    // set height of each line (height of text + 20%)
    lineHeight = (int) (calculateHeightFromFontSize(str, fontSize) * 1.2);
    // draw each line
    String line = "";
    for (int i = 0; i < lines.length; ++i) {

        if(calculateWidthFromFontSize(line + " " + lines[i], fontSize) <= drawSpace.width()){
            line = line + " " + lines[i];

        }else{
            canvas.drawText(line, x, y + yoffset, paint);
            yoffset = yoffset + lineHeight;
            line = lines[i];
        }
    }
    canvas.drawText(line, x, y + yoffset, paint);

}

private int calculateWidthFromFontSize(String testString, int currentSize)
{
    Rect bounds = new Rect();
    Paint paint = new Paint();
    paint.setTextSize(currentSize);
    paint.getTextBounds(testString, 0, testString.length(), bounds);

    return (int) Math.ceil( bounds.width());
}

private int calculateHeightFromFontSize(String testString, int currentSize)
{
    Rect bounds = new Rect();
    Paint paint = new Paint();
    paint.setTextSize(currentSize);
    paint.getTextBounds(testString, 0, testString.length(), bounds);

    return (int) Math.ceil( bounds.height());
}

这个答案包含了一个优秀的代码片段,该代码片段是由用户850688在此之前的回答中发现的https://dev59.com/eWgv5IYBdhLWcg3wF89P#11353080


drawSpace会是什么? - desgraci
drawSpace是一个Rect变量,你需要将它发送给方法,以便方法知道有多大的区域可以用来填充文本。 - Music Monkey
@MusicMonkey 每行的高度难道不正好等于字体大小吗? - android developer
@安卓开发者 是的,确实如此。但为了让文本看起来自然间隔,我们的眼睛通常会在上下约20%的间距上工作...否则每行文本将会看起来与上下行相接触。我可以重新编写那一行,以便行间距可以作为常量传递,但我发现“x 1.2”给了我一个一致而愉悦的视觉布局。 - Music Monkey

1

[]符号可能是换行符。由于某种原因,drawText()不知道如何处理换行符。

要么删除换行符,要么调用drawText()两次并偏移Y位置来模拟换行符。


谢谢。我不知道它不支持换行符,那真的很烦人。你所说的strip the newline是什么意思? - RoflcoptrException
使用 String.replace() 函数将所有的 "\n" 替换为 ""(空字符串)。 - Trevor Johns
1
啊是的,那不是问题,在上面的代码中只有单一情况需要它;正如你所看到的, "\n" 是我自己添加的。 - RoflcoptrException

0

而且我还为每行添加了“省略号”和“截断”:

Rect mBounds = new Rect();
void drawMultiLineString(Canvas canvas, TextPaint paint, String str, Rect drawingRect) {
    int lineHeight = 0;
    int yOffset    = 0;

    String[] lines = str.split("\n");
    for (String line : lines) {
        CharSequence txt = TextUtils.ellipsize(line, mTextPaint, drawingRect.right - drawingRect.left, TextUtils.TruncateAt.END);
        canvas.drawText(txt, 0, txt.length(), drawingRect.left, drawingRect.top + yOffset, paint);
        paint.getTextBounds(line, 0, line.length(), mBounds);
        lineHeight = (int) ((float) mBounds.height() * 1.2);
        yOffset += lineHeight;
    }
}

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