Android drawText including text wrapping

16,266

Solution 1

Yes, StaticLayout is what you're meant to use to draw multi-line text on a Canvas. Save yourself a world of pain and don't think about breaking text yourself -- you're on the right path.

I'm not sure about the bitmap problem, but your second code above worked just fine to draw text on a canvas for me.

Learn to use StaticLayout , then draw the Layout object onto a canvas using the Layout.draw() method.

References

Solution 2

public Bitmap drawMultilineTextToBitmap(Context gContext,
                                   int gResId,
                                   String gText) {

  // prepare canvas
  Resources resources = gContext.getResources();
  float scale = resources.getDisplayMetrics().density;
  Bitmap bitmap = BitmapFactory.decodeResource(resources, gResId);

  android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
  // set default bitmap config if none
  if(bitmapConfig == null) {
    bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
  }
  // resource bitmaps are imutable,
  // so we need to convert it to mutable one
  bitmap = bitmap.copy(bitmapConfig, true);

  Canvas canvas = new Canvas(bitmap);

  // new antialiased Paint
  TextPaint paint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
  // text color - #3D3D3D
  paint.setColor(Color.rgb(61, 61, 61));
  // text size in pixels
  paint.setTextSize((int) (14 * scale));
  // text shadow
  paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);

  // set text width to canvas width minus 16dp padding
  int textWidth = canvas.getWidth() - (int) (16 * scale);

  // init StaticLayout for text
  StaticLayout textLayout = new StaticLayout(
    gText, paint, textWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);

  // get height of multiline text
  int textHeight = textLayout.getHeight();

  // get position of text's top left corner
  float x = (bitmap.getWidth() - textWidth)/2;
  float y = (bitmap.getHeight() - textHeight)/2;

  // draw text to the Canvas center
  canvas.save();
  canvas.translate(x, y);
  textLayout.draw(canvas);
  canvas.restore();

  return bitmap;
}

source : http://www.skoumal.net/en/android-drawing-multiline-text-on-bitmap/

Share:
16,266

Related videos on Youtube

Mustafa Nasser
Author by

Mustafa Nasser

Updated on June 04, 2022

Comments

  • Mustafa Nasser
    Mustafa Nasser about 2 years

    I am currently creating an image editor and am attempting to draw text on top of on image using canvas.drawText(). So far I have been successful in doing this but when the user enters text that is too long, the text just continues on one line out of the page and doesn't wrap itself to the width of the screen. How would I go about doing this? I have tried using a static layout but cannot seem to get it to work, has anyone got a tutorial to do this?

    My function for drawing on a canvas using static layout:

     public Bitmap createImage(float scr_x,float scr_y,String user_text){
    
                Canvas canvas = new Canvas(image);
    
                scr_x = 100;
                scr_y = 100;
                final TextPaint tp = new TextPaint(Color.WHITE);     
                canvas.save();
                StaticLayout sl = new StaticLayout("" + user_text, tp, originalBitmap.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
                sl.draw(canvas);
    
             return image;
            }
    

    Okay, I've updated my code, but when I try to draw on the image nothing happens at all, I have no idea why either:

        public Bitmap createImage(String user_text) {
        // canvas object with bitmap image as constructor
        Canvas canvas = new Canvas(image);
        TextPaint tp = new TextPaint();
        tp.setColor(Color.RED);
        tp.setTextSize(50);
        tp.setTextAlign(Align.CENTER);
        tp.setAntiAlias(true);
        StaticLayout sl = new StaticLayout("" + user_text, tp,
                canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
        canvas.translate(100, 100);
        sl.draw(canvas);
        return image;
    }
    

    Is staticlayout not meant to be used to draw on canvas?

  • Mustafa Nasser
    Mustafa Nasser almost 11 years
    How do you mean? I'm really struggling with this as I'm pretty new. It seems from reading all other threads that the StaticLayout method is preferred?
  • Marcos Vasconcelos
    Marcos Vasconcelos almost 11 years
    Components that do extends View will not drawn anything until layout and measure is called, may you need call sl.measure(100,100,width, height) then draw. But I know that measuring characters width to wrap content can be done.
  • Lisa Wray
    Lisa Wray almost 11 years
    StaticLayout is specifically meant for rendering multi-line text, including handling line breaking for you. You should absolutely use it to draw text on a Canvas in any case where you "would be tempted to call Canvas.drawText() directly". Trust me, you do NOT want to get into your own line breaking. developer.android.com/reference/android/text/StaticLayout.ht‌​ml
  • Marcos Vasconcelos
    Marcos Vasconcelos almost 11 years
    Nice to know Lisa, just dont see a reason to downvote, but thanks anyway, will be helpfull for me also.
  • Marcos Vasconcelos
    Marcos Vasconcelos almost 11 years
    Please provide a sample, since StaticLayout dont has any direct draw method to a Canvas (and Canvas dont has any draw(text.layout))
  • Marcos Vasconcelos
    Marcos Vasconcelos almost 11 years
    Also my answer is correct, but it's not the best way.. just to you to see how unfair this is
  • Mustafa Nasser
    Mustafa Nasser almost 11 years
    I can confirm Marcos solution does indeed work, I forgot to add the following line at the end, iv_ttx.setImageBitmap(image).....Thank you Marco.
  • IntoTheDeep
    IntoTheDeep almost 8 years
    This answer did not help at all