How to use canvas in your android apps - Part 1


SDK Version: 
M3
If you want to use a custom layout with a canvas in your application, this tutorial may be useful to you. We will draw a kangoo at the end of this tutorial.


There is a cool article on site Custom View - HorizontalSlider, what you can use to understand the following code:

  1. [...]
  2. <com.helloandroid.canvastutorial.Panel android:id="@+id/SurfaceView01" android:layout_width="wrap_content"
  3.  
  4. android:layout_height="wrap_content" android:maxHeight="40dip">
  5. </com.helloandroid.canvastutorial.Panel>
  6. [...]

This is your main.xml.

Your main class extends Activity and similar as the following code snip:

  1. public class Canvastutorial extends Activity {
  2.     /** Called when the activity is first created. */
  3.     @Override
  4.     public void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         setContentView(R.layout.main);
  7.     }
  8. }

Your second class called Panel.java. This class extends SurfaceView and implements SurfaceHolder.Callback. The interface requires three additional methods we need to implement: surfaceCreated(), surfaceDestroyed(), surfaceChanged().

  1. class Panel extends SurfaceView implements SurfaceHolder.Callback {
  2.     @Override
  3.     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  4.         // TODO Auto-generated method stub
  5.     }
  6.  
  7.     @Override
  8.     public void surfaceCreated(SurfaceHolder holder) {
  9.         // TODO Auto-generated method stub
  10.     }
  11.  
  12.     @Override
  13.     public void surfaceDestroyed(SurfaceHolder holder) {
  14.         // TODO Auto-generated method stub
  15.     }
  16. }

Add this constructor to code to inicialize the panel:

  1.        public Panel(Context context, AttributeSet attrs) {
  2.                 super(context, attrs);
  3.                 // TODO Auto-generated constructor stub
  4.             getHolder().addCallback(this);
  5.             canvasthread = new CanvasThread(getHolder(), this);
  6.             setFocusable(true);
  7.         }

And modify the implemented methods to set your threads:

  1.         @Override
  2.         public void surfaceChanged(SurfaceHolder holder, int format, int width,
  3.                         int height) {
  4.                 // TODO Auto-generated method stub
  5.                
  6.         }
  7.         @Override
  8.         public void surfaceCreated(SurfaceHolder holder) {
  9.                 // TODO Auto-generated method stub
  10.             canvasthread.setRunning(true);
  11.             canvasthread.start();
  12.  
  13.                
  14.         }
  15.         @Override
  16.         public void surfaceDestroyed(SurfaceHolder holder) {
  17.                 // TODO Auto-generated method stub
  18.                 boolean retry = true;
  19.                 canvasthread.setRunning(false);
  20.                 while (retry) {
  21.                         try {
  22.                                 canvasthread.join();
  23.                                 retry = false;
  24.                         } catch (InterruptedException e) {
  25.                                 // we will try it again and again...
  26.                         }
  27.                 }
  28.  
  29.         }

Add this class to your project to create threads, which will control the drawings. We need a constructor with the Panel and the SurfaceHolder as parameters, a setter to set the variable which keeps the thread running and we need to override the method run().:

  1. package com.helloandroid.canvastutorial;
  2.  
  3. import android.graphics.Canvas;
  4. import android.view.SurfaceHolder;
  5.  
  6. public class CanvasThread extends Thread {
  7.     private SurfaceHolder _surfaceHolder;
  8.     private Panel _panel;
  9.     private boolean _run = false;
  10.  
  11.     public CanvasThread(SurfaceHolder surfaceHolder, Panel panel) {
  12.         _surfaceHolder = surfaceHolder;
  13.         _panel = panel;
  14.     }
  15.  
  16.     public void setRunning(boolean run) {
  17.         _run = run;
  18.     }
  19.  
  20.     @Override
  21.     public void run() {
  22.         Canvas c;
  23.         while (_run) {
  24.             c = null;
  25.             try {
  26.                 c = _surfaceHolder.lockCanvas(null);
  27.                 synchronized (_surfaceHolder) {
  28.                     _panel.onDraw(c);
  29.                 }
  30.             } finally {
  31.                 // do this in a finally so that if an exception is thrown
  32.                 // during the above, we don't leave the Surface in an
  33.                 // inconsistent state
  34.                 if (c != null) {
  35.                     _surfaceHolder.unlockCanvasAndPost(c);
  36.                 }
  37.             }
  38.         }
  39.     }
  40. }

The last thing, add an onDraw method to your panel:

  1.         @Override
  2.         public void onDraw(Canvas canvas) {
  3.                
  4.                 Paint paint = new Paint();
  5.                
  6.  
  7.                 Bitmap kangoo = BitmapFactory.decodeResource(getResources(),
  8.                                 R.drawable.kangoo);
  9.                 canvas.drawColor(Color.BLACK);
  10.                 canvas.drawBitmap(kangoo, 10, 10, null);
  11.                
  12.         }
  13.          

If you need my image, you can download from here:



Copy this image to drawable folder and refresh your project.

It will draw a kangoo. :) Next time I will show you some drawing commands. Feel free to download the source code from Here.