How to draw multiline text to canvas easily


SDK Version: 
M3

There are situations where you have to use a Canvas. What do you do if you have more text than you can properly display?
The problem is, that if you want multiline text on canvas, with the drawText method, you would have to measure how much space a single line of text would take up, and also compare it to the width of the screen, and draw each line separately.
Read more to check my solution.

I tought to myself, hey why not use a TextView, add the text, use it's word wrap properties, than get a bitmap from it, and draw it on canvas.
I made a helper class, that extends View:

  1. public class CanvasHelper extends View {
  2.  
  3.         String mText;
  4.         Context mContext;
  5.         Paint paint = new Paint();
  6.  
  7.         public CanvasHelper(Context context) {
  8.                 super(context);
  9.                 mContext = context;
  10.                 paint.setColor(Color.WHITE); // You could setup the background etc here
  11.                 paint.setStyle(Style.FILL);
  12.         }
  13.  
  14.         @Override
  15.         protected void onDraw(Canvas canvas) {
  16.                 super.onDraw(canvas);
  17.                 drawTextOnCanvas(canvas, mText);
  18.         }
  19.  
  20.         private void drawTextOnCanvas(Canvas canvas, String text) {
  21.                 // maybe color the bacground..
  22.                 canvas.drawPaint(paint);
  23.  
  24.                 // Setup a textview like you normally would with your activity context
  25.                 TextView tv = new TextView(mContext);
  26.  
  27.                 // setup text
  28.                 tv.setText(mText);
  29.  
  30.                 // maybe set textcolor
  31.                 tv.setTextColor(Color.BLACK);
  32.  
  33.                 // you have to enable setDrawingCacheEnabled, or the getDrawingCache will return null
  34.                 tv.setDrawingCacheEnabled(true);
  35.  
  36.                 // we need to setup how big the view should be..which is exactly as big as the canvas
  37.                 tv.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
  38.  
  39.                 // assign the layout values to the textview
  40.                 tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
  41.  
  42.                 // draw the bitmap from the drawingcache to the canvas
  43.                 canvas.drawBitmap(tv.getDrawingCache(), 0, 0, paint);
  44.  
  45.                 // disable drawing cache
  46.                 tv.setDrawingCacheEnabled(false);
  47.         }
  48.  
  49.         public void setText(String text) {
  50.                 this.mText = text;
  51.         }
  52. }

Usage would be something like this:

  1. public class MultiLineCanvasActivity extends Activity {
  2.  
  3.         @Override
  4.         public void onCreate(Bundle savedInstanceState) {
  5.                 super.onCreate(savedInstanceState);
  6.  
  7.                 String text = "Venison turkey short loin  pork belly tri-tip. Pastrami jerky pancetta tail salami shoulder. Ribeye ball tip short loin, andouille shankle pork chop shank short ribs pork belly tongue jerky beef venison pig pork. Bresaola t-bone cow rump flank. Ball tip spare ribs strip steak, cow beef ribs corned beef chuck chicken salami hamburger shankle drumstick. Venison ham beef sirloin, pastrami meatloaf brisket tail ball tip chicken bacon. Shank shoulder tail cow short loin tenderloin, pork ground round tongue salami jowl short ribs turkey t-bone fatback.";
  8.  
  9.                 CanvasHelper ch = new CanvasHelper(this);
  10.                 ch.setText(text);
  11.                 setContentView(ch);
  12.         }
  13. }

On the nexus one:

nexus

On the HTC Wildfire:
nexus

On the Acer Iconica A500:
nexus