|
||||||||||||||||||||||||||||||||||||||
|
Threaded drawings :: Continously The here explained approach repaints the drawing surface continuously as fast as the GPU can handle it. First of all, we need to create a class that extends the SurfaceView class. I named it DrawSurface. package lu.fisch.template;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class DrawSurface extends SurfaceView implements SurfaceHolder.Callback {
// a reference to the drawing thread
private DrawThread drawThread = null;
// your application certainly needs some data model
private Object dataModel;
public DrawSurface(Context context) {
super(context);
init(context);
}
public DrawSurface(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawSurface(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context)
{
// register our interest in hearing about changes to our surface
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// make sure we get key events
setFocusable(true);
// in case your application needs one or more timers,
// you have to put them here
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// do something
}
}, 10, 10);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// react on touch events
return true;
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder arg0)
{
// as the constructor is not being called if
// we resume from a previous state, we need
// to create the drawing thread here.
if(drawThread==null)
{
drawThread = new DrawThread(getHolder(), getContext(), new Handler() {
@Override
public void handleMessage(Message m) {
}
});
// call the setter for the pointer to the model
drawThread.setDataModel(dataModel);
}
// start if not yet or still alive
if(!drawThread.isAlive())
drawThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0)
{
drawThread.setRunning(false);
// stop the drawThread properly
boolean retry = true;
while (retry)
{
try
{
// wait for it to finish
drawThread.join();
retry = false;
}
catch (InterruptedException e)
{
// ignore any error
}
}
// set it to null, so that a new one can be created in case of a resume
drawThread=null;
}
}
We next need to create the thread that actually does the painting. I named it DrawThread. package lu.fisch.template;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.view.SurfaceHolder;
public class DrawThread extends Thread {
/** Handle to the surface manager object we interact with */
private SurfaceHolder mSurfaceHolder;
/** Handle to the application context, used to e.g. fetch Drawables. */
private Context mContext;
/** Message handler used by thread to interact with TextView */
private Handler mHandler;
// indicates weather we are running or not
private boolean running = false;
private Object dataModel = new Object();
public DrawThread(SurfaceHolder surfaceHolder,
Context context,
Handler handler)
{
// get handles to some important objects
mSurfaceHolder = surfaceHolder;
mHandler = handler;
mContext = context;
}
public void setDataModel(Object dataModel)
{
this.dataModel=dataModel;
}
private void draw(Canvas c)
{
if(running)
{
// do your paintings here ...
// clean background
Paint paint = new Paint();
paint.setColor(Color.BLACK);
c.drawRect(0, 0, c.getWidth(), c.getHeight(), paint);
// draw some random lines
paint = new Paint();
paint.setColor(Color.WHITE);
for(int i=0;i<10;i++)
{
c.drawLine((float) (Math.random()*c.getWidth()),(float) (Math.random()*c.getHeight()),
(float) (Math.random()*c.getWidth()),(float) (Math.random()*c.getHeight()), paint);
}
}
}
@Override
public void run()
{
while(running)
{
Canvas c = null;
try
{
// get the surface
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder)
{
if(c!=null)
{
draw(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)
{
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
@Override
public void start()
{
super.start();
setRunning(true);
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
}
In order to add it to your activity, you have to add these lines of code to you XML file: <lu.fisch.template.DrawSurface
android:id="@+id/drawpanel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="@dimen/None"
android:paddingTop="@dimen/None" />
|
|||||||||||||||||||||||||||||||||||||