Android – Drawing multiline text on canvas

If you always wanted to know how to draw multiline text on canvas you came to the right place. Meet StaticLayout, your new best friend when it comes to drawing text on canvas.

I stumbled upon this class while developing a custom Watch Face for Android Wear. When it comes to Android Wear you’re dealing with very small canvas and you have to think how and where your text will be placed. Drawing multiline text is actually pretty simple and this is what you need to do:

1. Initialize Paint object. Use TextPaint which is an extension of Paint.

//Set your own color, size etc.
TextPaint textPaint = new TextPaint();

2. onDraw method is the place where the fun things happen.

@Override 
public void onDraw (Canvas canvas, Rect bounds) { 
    super.onDraw(canvas, bounds);

    String textOnCanvas = "I registered koc.sexy so that my package 
         name can start with sexy.koc";

    //Static layout which will be drawn on canvas
    //textOnCanvas - text which will be drawn
    //text paint - paint object
    //bounds.width - width of the layout
    //Layout.Alignment.ALIGN_CENTER - layout alignment
    //1 - text spacing multiply
    //1 - text spacing add
    //true - include padding
    StaticLayout sl = new StaticLayout(textOnCanvas, textPaint, bounds.width(),
           Layout.Alignment.ALIGN_CENTER, 1, 1, true);

    canvas.save();

    //calculate X and Y coordinates - In this case we want to draw the text in the 
    //center of canvas so we calculate
    //text height and number of lines to move Y coordinate to center.
    float textHeight = getTextHeight(textOnCanvas, textPaint);
    int numberOfTextLines = sl.getLineCount();
    float textYCoordinate = bounds.exactCenterY() - 
         ((numberOfTextLines * textHeight) / 2);

    //text will be drawn from left
    float textXCoordinate = bounds.left;

    canvas.translate(textXCoordinate, textYCoordinate);

    //draws static layout on canvas
    sl.draw(canvas);
    canvas.restore();
 
} 

/**
 * @return text height
 */
private float getTextHeight(String text, Paint paint) {

    Rect rect = new Rect();
    paint.getTextBounds(text, 0, text.length(), rect);
    return rect.height();
}

And this is how the text will look like:

Multiline text on canvas

If your text is going to change you can use DynamicLayout which updates itself as the text is edited

Although this example is done on Watch Face canvas, you can also use StaticLayout when developing mobile applications.

  • kevin underscore

    this is awesome and helpful. tnx!

  • Nikola Vasiljevski

    Great article! I have a question, do you have any suggestion on how would it be possible to draw the text top to bottom, like the image below?

  • Nice post. Two points. First, the “text spacing add” argument to the StaticLayout constructor should be zero. There’s no good reason to add one extra pixel between each line. Second, the allocation of the StaticLayout object should be moved out of the onDraw() method; the place for it is in onSurfaceChanged(), when the view’s bounds are known. (For mobile devices, that would be in onLayout() or onSizeChanged().)

    • z zg

      hi,i want to draw some long texts on canvas with indent in first line(as the attachment image below showed), can you tell me how to achieve with the staticlayout?Thanks~

      • You can apply a LeadingMarginSpan.Standard to the text. It takes two parameters: the margin for the first line and the margin for the remaining lines.