4

I got an app that the user insert a text, and when he clicks on a button, it generates a new image with that text in a predeterminated image and saves it on the phone.

But sometimes that text is too long and exceeds the image's width, so what I'm trying to do is break it into a new line. How should I do it?

I tried with breakText, but I'm not sure how to use it... I was using:

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

But it didn't work.

Also, when I manually break the line at the EditText it shows everything in only one and with a "[]" where the second line should start...

EDIT: My code original code:

    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);
}
Victor Santiago
  • 902
  • 1
  • 10
  • 20

2 Answers2

3

breatText returns the number of characters in the string that may can be displayed if before being cut off. I would suggest calling it in a loop. Removing however many characters it can fit and placing them in a string each iteration until the source text is empty.:

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

As for printing multiple lines. I'm assuming you're using Canvas.drawText which does not seem to support line breaks. So you'll need to draw each line separately with different Y-Values. (Code adapted from here):

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

EDIT I don't see in your code where you actually split the strings as I described. I can't diagnose why my solution didn't work if you don't actually show me how you implemented it.

Working from here though I think I can show you how to fix the error. If you want to do it multiple times it would be a good idea to write a method for it. Add the following method to your class:

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

Replace this code:

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

With this code:

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

EDIT 2:

Here is the code I used to set up and text your code:

    // 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();
Community
  • 1
  • 1
Fr33dan
  • 4,227
  • 3
  • 35
  • 62
  • Yes, I'm using drawText. Didn't know that it doesn't support line breaks, too bad... I'm trying to adapt this code for my project but I can't make it work, I keep getting an image with only one line. – Victor Santiago Aug 30 '12 at 23:15
  • Could you add the code in which you draw the string to your question? – Fr33dan Aug 31 '12 at 01:26
  • Sorry, I editted with my original code. I tried with this method and replaced the code, but it still doesn't work. It saves the image on my sdcard but there's no caption on it. – Victor Santiago Aug 31 '12 at 20:24
  • Try playing with your largura, altura2, altura. It took me a while to find the right values that would work properly. drawText seems to draw upward from the y-coordinate if this helps (threw me for a loop). I've edited my answer again to show you what I used. – Fr33dan Sep 01 '12 at 05:00
  • I played with the values and I was able to see the text. I used yours also, and it's drawing the text but I keep getting the same result, it's just a one line text. Here: http://i.imgur.com/TnMN9.jpg Well, fortunately I got a solution for this problem, but anyway thank you very much! – Victor Santiago Sep 05 '12 at 23:47
  • Thanks it worked grate... and I have found a small bus in your code u have used while(test.isEmpty()){..} it will never go inside while loop that's the reason @CavemanWithInternet don't see text so I have updated ur answer – Jaiprakash Soni Dec 26 '13 at 08:01
  • @JaiSoni Hmm I thought I had tested this before I answered but looking at the code you are right, it should not split the string properly. Unfortunately I do not have a working Android phone at the moment so I cannot retest it. I will still change the code (your edit was rejected) as you stated, but I will leave it as a while instead of a do-while because the loop does not need to run at all if the parameter text is empty to begin with. – Fr33dan Dec 26 '13 at 14:35
0

I found a solution, I created a layout and set the string as a textview and the image as a background and drawed it.

Victor Santiago
  • 902
  • 1
  • 10
  • 20
  • Can you please guide me how you had drawn layout contents on canvas ? I am having the same issue. – AndyN Dec 06 '13 at 12:00