I've seen many posts dealing with similar problems but none of them worked for me. In Canvas, I have a rectangle of size, let's say, 200px by 200px, and I want to write text in this rectangle. The text doesn't need to fill the entire rectangle, but the important thing is that there should automatically be a line break when it reaches the end of the rectangle. How can I do this in Android?
            Asked
            
        
        
            Active
            
        
            Viewed 1.1k times
        
    11
            
            
        - 
                    I think is a better solution to wrap a TextView inside a custom layout you can easily do and set width and height of your TextView to "fill_parent".It fits your purpose.:) – Daniel Conde Marin Oct 16 '12 at 18:13
4 Answers
34
            You can use StaticLayout.
RectF rect = new RectF(....)
StaticLayout sl = new StaticLayout("This is my text that must fit to a rectangle", textPaint, (int)rect.width(), Layout.Alignment.ALIGN_CENTER, 1, 1, false);
canvas.save();
canvas.translate(rect.left, rect.top);
sl.draw(canvas);
canvas.restore();
 
    
    
        Igor B.
        
- 1,134
- 9
- 6
- 
                    2Thank you! I've never come across StaticLayout before and I can use it to clean up some fugly code I've got in my apps. – Simon Oct 16 '12 at 18:54
- 
                    You can also replace StaticLayout by [DynamicLayout](http://developer.android.com/reference/android/text/DynamicLayout.html) if you need to change the text afterwards. – Louis CAD Aug 25 '15 at 14:41
- 
                    @LouisCAD i dont see any method for editing textafter creating object. there are no setter present in this class. – Ramiz Ansari Nov 24 '17 at 22:58
- 
                    @RamizAnsari You're right, however, the `CharSequence` you pass in the `DynamicLayout` constructor can be edited afterwards. It can take an `Editable` for example, or your `CharSequence` implementation that delegates to a String you can swap. – Louis CAD Nov 25 '17 at 13:25
3
            
            
        You'll need to measure the text and then break it yourself in code. Paint.measureText is what you need.
 
    
    
        Khantahr
        
- 8,156
- 4
- 37
- 60
1
            
            
        public class MutilineText {
private String mText;
private int fontSize = 50;
public MutilineText(String text) {
    this.mText = text;
}
public String getText() {
    return mText;
}
public void setText(String text) {
    mText = text;
}
public void draw(Canvas canvas, Rect drawSpace) {
    Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
    paintText.setAntiAlias(true);
    paintText.setDither(true);
    paintText.setColor(Color.BLACK);
    paintText.setStyle(Paint.Style.FILL);
    paintText.setStrokeWidth(3);
    paintText.setTextSize(fontSize);
    drawMultilineText(mText, drawSpace.left, drawSpace.top + 15, paintText, canvas, fontSize, drawSpace);
}
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("\n");
    lineHeight = (int) (calculateHeightFromFontSize(str, fontSize) * 1.4);
    String line = "";
    for (int i = 0; i < lines.length; ++i) {
        if (calculateWidthFromFontSize(line, fontSize) <= drawSpace.width()) {
            canvas.drawText(line, x + 30, y + yoffset, paint);
            yoffset = yoffset + lineHeight;
            line = lines[i];
        } else {
            canvas.drawText(divideString(line, drawSpace.width()), x + 30, y + yoffset, paint);
        }
    }
}
private String divideString(String inputString, int bound) {
    String ret = inputString;
    while (calculateWidthFromFontSize(ret, fontSize) >= bound) {
        ret = ret.substring(0, (ret.length() - 1));
    }
    ret = ret.substring(0, ret.length() - 3) + "...";
    return ret;
}
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());
}
 
    
    
        Enrico Bruno Del Zotto
        
- 159
- 9
- 
                    1No code only answers please, add comments to explain what you are doing. – Guillaume F. Jun 17 '16 at 17:00
0
            
            
        could you just use a textfield on top of your canvas and enable multiline for the that textfield - then you would be done as in textfield line breaks comes for free ;-)
 
    
    
        dorjeduck
        
- 7,624
- 11
- 52
- 66
 
    