Recommend Reading: Draw Animation on Canvas Example

Android provide a full functions on Graphics. Commonly, we can use 2D graphics library and OpenGL ES 1.0 for 3D graphic. In this post, I gonna to introduce the 2D graphics, and give you a 2D graphics canvas example. Usually, when we try to draw 2D graphics, as android developer page say, we have two ways to choose:

  1. Draw your graphics or animations into a View object from your layout.
  2. Draw your graphics directly to a Canvas.

Draw graphics directly to a Canvas is a little bit complicated. You can go to the android developer page for farther details. The following example will show you how to draw a bitmap on the canvas, when you click the canvas.

Android Canvas Example screenshot
Android Canvas Example Screenshot

Download And Try APK File

As some friends gave me the feed back that the old application would crash after running for a while. So I improve this example code a little bit to fix this problem. And some people also don’t know how to use this application. They just saw a black screen when they started to run the demo. If you read the example code, you will understand that you need to touch the screen to start the drawing process.

New Update:

  1. Fix the application crashing bug.
  2. Add one text instruction

Check the latest android canvas example apk here
chart

As android dev guide says, when you’re writing an application in which you would like to perform specialized drawing and/or control the animation of graphics, you should do so by drawing through a Canvas. When we do so, we will put our drawing code in onDrwa() callback method, and Canvas will be pass from the function parameter. And we also can get a canvas by calling SurfaceHolder.lockCanvas();

In my canvas example, we will put a SurfaceView on the stage, and when you click the surfaceview, it will draw the bitmap image on the canvas. This is the main.xml example:

<!--?xml version="1.0" encoding="utf-8"?-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<com.jms.DrawImage.DrawCanvas  
	android:id="@+id/SurfaceView01"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    />
</LinearLayout>

There is our customized class DrawCanvas, while extends from SurfaceView:

public class DrawCanvas extends SurfaceView implements Callback {
private CanvasThread canvasThread;

public DrawCanvas(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

public DrawCanvas(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub

this.getHolder().addCallback(this);
this.canvasThread = new CanvasThread(getHolder());
this.setFocusable(true);
}

public DrawCanvas(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub

}

public void startDrawImage() {
canvasThread.setRunning(true);
canvasThread.start();
}

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub

}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
boolean retry = true;
canvasThread.setRunning(false);
while(retry) {
try {
canvasThread.join();
retry = false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Bitmap sweet = BitmapFactory.decodeResource(getResources(), R.drawable.sq);
canvas.drawColor(color.black);
canvas.drawBitmap(sweet, 0, 0, null);
}

private class CanvasThread extends Thread {
private SurfaceHolder surfaceHolder;
private boolean isRun = false;

public CanvasThread(SurfaceHolder holder) {
this.surfaceHolder = holder;
}

public void setRunning(boolean run) {
this.isRun = run;
}

@Override
public void run() {
// TODO Auto-generated method stub
Canvas c;

while(isRun) {
c = null;
try {
c = this.surfaceHolder.lockCanvas(null);
synchronized(this.surfaceHolder) {
DrawCanvas.this.onDraw(c);
}
} finally {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}

Here is the Activity code example:

public class DrawImage extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

DrawCanvas mycanvas = (DrawCanvas)findViewById(R.id.SurfaceView01);
mycanvas.setOnClickListener(clickListener);
}

private OnClickListener clickListener = new OnClickListener() {
private boolean isDrawn = false;
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(!isDrawn) {
DrawCanvas mycanvas = (DrawCanvas)findViewById(R.id.SurfaceView01);
mycanvas.startDrawImage();
isDrawn = true;
}
}
};
}

As you see above, in the activity, we define a OnClickListener. Inside we will call our canvas to draw the bitmap. In the DrawCanvas sample, you can find the function startDrawImage(), and it will start a thread to call back the onDraw() function, which will draw the real bitmap on the canvas.

Download Canvas Example

How to Fix the Crash Bug


In our customized class DrawCanvas, change the function onDraw(Canvas canvas) as following:

	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		Bitmap sweet = BitmapFactory.decodeResource(getResources(), R.drawable.sq);
		canvas.drawColor(color.black);
		canvas.drawBitmap(sweet, 0, 0, null);
		
		canvasThread.setRunning(false);
	}
Previous PostNext Post

9 Comments

  1. Respected Sir,
    Please give me more suggestion, how to use a dynamic animation in android app.


    Thanks & Regards,
    Ranjeet Kushwaha
    7503709347

  2. Hello dude,
    I am using the static image in bitmap, now i want to fill the colors into that image. i am able to draw the color in side the image but at stroke points also filling with colors. pleas can u help me in that, i want fill the color only inside not on borders of out line image.

    1. What drawing method are you using? canvas.drawColor will fill the entire canvas with the specified color.

      If you want to fill one area, I think you can draw an rectangle for example.

Leave a Reply to jhansi Cancel reply

Your email address will not be published. Required fields are marked *