在图像中绘制文本时如何换行

4

我有一个应用程序,用户插入文本后,点击按钮,它会生成一个新的图片,其中包含预设图像中的该文本,并将其保存在手机上。

但是有时候文本太长了,超过了图片的宽度,因此我想要把它分成一行。我应该怎么做?

我尝试使用breakText,但不确定如何使用它...我正在使用:

        textPaint.breakText(text[2], true, bmp.getWidth(), null);

但它没有起作用。

此外,当我手动在EditText处换行时,它只显示一行并在第二行应该开始的位置上显示"[]"...

编辑:我的原始代码:

    private void SaveMyImage() {
    // TODO Auto-generated method stub
    File myDir = new File(Environment.getExternalStorageDirectory().getPath()+"/App/");
    myDir.mkdirs();
    File file = new File (myDir, fname);
    if (file.exists ()) file.delete (); 
    try {
        FileOutputStream out = new FileOutputStream(file);

        Canvas canvas = new Canvas(bmp); 
        Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        if (text[0].equals("Image 01")) {
            textPaint.setColor(Color.BLACK);
        }
        else {
            textPaint.setColor(Color.WHITE);
        }
        textPaint.setTextAlign(Align.CENTER);
        textPaint.setTextSize(tamanho);
        textPaint.setShadowLayer(2, 2, 2, Color.BLACK);
        textPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); // Text Overlapping Pattern
        canvas.drawBitmap(bmp, 0, 0, null);
        canvas.drawText(text[1], largura, altura2, textPaint);
        canvas.drawText(text[2], largura, altura, textPaint);
        bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
        out.flush();
        out.close();
        Toast.makeText(SaveIMG.this, "Image saved on phone", Toast.LENGTH_LONG).show();
    } catch (Exception e) {
       e.printStackTrace();
    }
    sendBroadcast(new Intent(
            Intent.ACTION_MEDIA_MOUNTED,
            Uri.parse("file://" + Environment.getExternalStorageDirectory())));
    uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/App/"+fname);
    pronto.setImageURI(uri);
}
2个回答

3

breatText 返回字符串中可以显示的字符数,如果在被截断之前。我建议在循环中调用它。每次迭代删除它可以容纳的字符,并将它们放入一个字符串中,直到源文本为空为止。

ArrayList<String> lines = new ArrayList<String>();
String test = text[2];
while(!test.isEmpty()){
    int newLength = textPaint.breakText(test, true, bmp.getWidth(), null);
    lines.add(test.substring(0, newLength));
    test = test.substring(newLength);
}

关于打印多行。我假设您正在使用Canvas.drawText,它似乎不支持换行符。因此,您需要分别绘制每一行,并使用不同的Y值。(代码改编自此处):
Rect bounds = new Rect();
int yoff = 0;
for(String line:lines){
    canvas.drawText(line, x, y + yoff, paint);
    textPaint.getTextBounds(line, 0, line.length(), bounds);
    yoff += bounds.height();
}

编辑 我在你的代码中没有看到你实际上如何按照我描述的那样拆分字符串。如果您不向我展示您如何实现它,我无法诊断为什么我的解决方案不起作用。

不过从这里开始,我认为我可以向您展示如何修复错误。如果您想多次执行它,编写一个方法是个好主意。将以下方法添加到您的类中:

public void splitAndDrawLines(Canvas canvas,String text, int x, int y, Paint textPaint, int width){
    ArrayList<String> lines = new ArrayList<String>();
    String test = text;
    while(!test.isEmpty()){
        int newLength = textPaint.breakText(test, true, canvas.getWidth(), null);
        lines.add(test.substring(0, newLength));
        test = test.substring(newLength);
    }
    Rect bounds = new Rect();
    int yoff = 0;
    for(String line:lines){
        canvas.drawText(line, x, y + yoff, textPaint);
        textPaint.getTextBounds(line, 0, line.length(), bounds);
        yoff += bounds.height();
    }
}

替换此代码:

canvas.drawText(text[1], largura, altura2, textPaint);
canvas.drawText(text[2], largura, altura, textPaint);

使用这段代码:

this.splitAndDrawLines(canvas, text[1], largura, altura2, textPaint);
this.splitAndDrawLines(canvas, text[2], largura, altura, textPaint);

编辑2:

这是我用来设置和测试您的代码的代码:

    // Create a 100x100 bitmap
    bmp = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    // Set the height of the text to 12.
    this.tamanho = 12f;
    // Draw the text in the middle of the picture width-wise.
    this.largura = bmp.getWidth() / 2;
    // Text parameters
    this.text = new String[]{"MAKE THE TEXT WHITE", "This text starts in the middle of the middle is too long and will be split","Short text at the top of the image"}; 
    // Start one line size into the picture height-wise.
    this.altura = this.tamanho;
    // Start in the middle of the picture height-wise.
    this.altura2 = bmp.getHeight()/2;
    // Output File name.
    this.fname = "TEST.jpg";
    // Save the image
    SaveMyImage();

是的,我正在使用drawText。没想到它不支持换行,真可惜...我正试图将这段代码适应到我的项目中,但无论如何都无法使其正常工作,生成的图像始终只有一行。 - Victor Santiago
尝试调整你的largura、altura2和altura参数,需要一些时间来找到适当的值。如果有帮助的话,drawText似乎是从y坐标向上绘制(这让我有些困惑)。我已经编辑了我的回答,向你展示了我使用的方法。 - Fr33dan
我尝试了一下值,成功看到了文本。我也使用了你的值,它在绘制文本,但结果始终相同,只有一行文本。在这里:http://i.imgur.com/TnMN9.jpg 好消息是,我找到了解决方案,但无论如何还是非常感谢你! - Victor Santiago
谢谢,它很好用...我在你的代码中发现了一个小错误,你使用了while(test.isEmpty()){..},它永远不会进入while循环,这就是@CavemanWithInternet看不到文本的原因,所以我更新了你的答案。 - Jaiprakash Soni
@JaiSoni 嗯,我以为在回答之前已经测试过了,但看着代码,你是对的,它不应该正确地分割字符串。不幸的是,我目前没有可用的安卓手机,所以无法重新测试。我仍然会更改代码(你的编辑被拒绝了),如你所述,但我会将其保留为 while 循环,而不是 do-while,因为如果参数文本一开始就为空,循环根本不需要运行。 - Fr33dan
显示剩余2条评论

0
我找到了一个解决方案,我创建了一个布局,将字符串设置为TextView,将图像设置为背景并绘制它。

请问您能指导我如何在画布上绘制布局内容吗?我遇到了同样的问题。 - AndyN

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