android10

  • Increase font size
  • Default font size
  • Decrease font size

Playing with graphics in Android – Part II

E-mail Print
( 3 Votes )
Share

Introduction

If you didn't see the first part, go here.

Graphics in Android - Part II

The second part of this series will show what you have to change to switch from using the View class to SurfaceView class.

Just to remember, our last code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.droidnova.android.tutorial2d;
 
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
 
public class Tutorial2D extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new Panel(this));
}
 
class Panel extends View {
public Panel(Context context) {
super(context);
}
 
@Override
public void onDraw(Canvas canvas) {
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(_scratch, 10, 10, null);
}
}
}

 

Now lets simply change the super class of our Panel from View to SurfaceView.

1
2
3
// code snipped
class Panel extends SurfaceView {
// code snipped

 

Lets compile and start and you will see…. nothing.
The reason therefor is, that we need the SurfaceHolder, which provide us with the canvas we can draw on.

So one more change: use SurfaceHolder.Callback interface. The interface requires 3 additional methods we need to implement: surfaceCreated(), surfaceDestroyed(), surfaceChanged()

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

 

Additional we have to add the Panel to the SurfaceHolder for a callback. We will do this in the Panel constructor.

1
2
3
4
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
}

 

The next big thing: We need a Thread which will control the drawings. Lets create the inner class TutorialThread which extends from Thread class. 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class TutorialThread extends Thread {
private SurfaceHolder _surfaceHolder;
private Panel _panel;
private boolean _run = false;
 
public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
 
public void setRunning(boolean run) {
_run = run;
}
 
@Override
public void run() {
 
}
}

 

Now lets use the TutorialThread in our Panel:

1
2
3
4
5
6
7
8
9
class Panel extends SurfaceView implements SurfaceHolder.Callback {
private TutorialThread _thread;
 
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this);
}
// code snipped

 

We can also implement the methods surfaceCreated() and surfaceDestroyed(). The method surfaceCreated() after the surface was created. So we can set our running variable to true and start the thread.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public void surfaceCreated(SurfaceHolder holder) {
_thread.setRunning(true);
_thread.start();
}
 
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// simply copied from sample application LunarLander:
// we have to tell thread to shut down & wait for it to finish, or else
// it might touch the Surface after we return and explode
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}

 

Now we are near the finish line because we just have to implement the run() method.
First of all we need a Canvas object (line 3). Then a while loop with our _run variable (line 4)
Inside the loop we set our Canvas object to null and open a try block (line 5-6).
Inside this try block, we have to lock the canvas, draw on it, unlock and post it.
We are inside of a thread, so we have to synchronize at least our drawing with the SurfaceHolder (line 8-10).
We unlock and post it in the finally block to make sure, we don’t leave the Surface in an inconsistent state.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}

 

Finally we should have this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package com.droidnova.android.tutorial2d;
 
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
 
public class Tutorial2D extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new Panel(this));
}
 
class Panel extends SurfaceView implements SurfaceHolder.Callback {
private TutorialThread _thread;
 
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this);
}
 
@Override
public void onDraw(Canvas canvas) {
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(_scratch, 10, 10, null);
}
 
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
 
}
 
@Override
public void surfaceCreated(SurfaceHolder holder) {
_thread.setRunning(true);
_thread.start();
}
 
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// simply copied from sample application LunarLander:
// we have to tell thread to shut down & wait for it to finish, or else
// it might touch the Surface after we return and explode
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
 
class TutorialThread extends Thread {
private SurfaceHolder _surfaceHolder;
private Panel _panel;
private boolean _run = false;
 
public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
 
public void setRunning(boolean run) {
_run = run;
}
 
@Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}

 

Screenshot which shows the same icon as in part I.

graphics_in_android_01


Goto Part III
Comments (0)
Only registered users can write comments!
 

ANDROID10 --- TIP!!!

android10 tipYou can edit your position easily: just click on your picture when you're logged in, then on the top you will find a menu, go there, edit your profile, go to your position tab and drag the icon in the map. That's all. Just easy!!!
contact android10!!!