首页 > 代码库 > SurfaceViewDemo

SurfaceViewDemo

SurfaceView是使用的双缓冲机制,所以在性能上面是比view更优越的类,在使用SurfaceView的时候其实并不是和SurfaceView直接打交道,而是通过SurfaceHolder的实例来控制SurfaceView的大小和格式等,并且主要用于监听surfaceview的状态,获取canvas对象的方式即通过surfaceholder的lockcanvas()方法锁定画布,并且返回一个canvas,然后就可以在获得的画布上面大展手脚了!!!当绘制完毕的时候通过surfaceholder的unloccanvasandpost();方法即可解锁画布,并且提交。

当对surfaceview进行监听的时候必须实现surfaceholder的callback接口即必须重写三个函数:surfacechanged、surfacecreated、surfacedestroyed最后通过surfaceholder类的addcallback(Callback callback);方法将其监听借口实例传入,即可完成对surfaceView的监听。以下是一个小的demo:

MSurfaceView.java

public class MSurfaceView extends SurfaceView implements Callback{    private Paint paint;    private SurfaceHolder holder;    private int x, y;    private int radius;    public MSurfaceView(Context context){        super(context);        // TODO Auto-generated constructor stub        paint = new Paint();        holder = this.getHolder();        holder.addCallback(this);        paint.setColor(Color.RED);    }    @Override    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {        // TODO Auto-generated method stub        //mDraw();    }    @Override    public void surfaceCreated(SurfaceHolder arg0) {        // TODO Auto-generated method stub            }    @Override    public void surfaceDestroyed(SurfaceHolder arg0) {        // TODO Auto-generated method stub            }     public void mDraw(){        Canvas canvas = holder.lockCanvas();        canvas.drawText("HELLO SURFACEVIEW", x, y, paint);        canvas.drawCircle(x, y, setRadius(), paint);        holder.unlockCanvasAndPost(canvas);    }    private int setRadius(){        radius = (int)(Math.random()*20);        return radius;    }    @Override    public boolean onTouchEvent(MotionEvent event) {        // TODO Auto-generated method stub        x = (int)event.getX();        y = (int)event.getY();        mDraw();        return true;    }        }

在Mainactivity.java文件里面将surfaceView作为当前显示的view:

public class MainActivity extends Activity  {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(new MSurfaceView(this));    }}

运行效果如下:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

现在实现通过自定义一个线程来绘制surfaceview,线程的定义通过implements Runnable接口来完成,代码做如下修改:

public class MSurfaceView extends SurfaceView implements Callback, Runnable{    private Paint paint;    private SurfaceHolder holder;    private int x, y;    private int radius;    private Thread mThread;    private boolean threadstate;    public MSurfaceView(Context context){        super(context);        // TODO Auto-generated constructor stub        paint = new Paint();        holder = this.getHolder();        holder.addCallback(this);        paint.setColor(Color.RED);        setFocusable(true);    }    @Override    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {        // TODO Auto-generated method stub        //mDraw();            }    @Override    public void surfaceCreated(SurfaceHolder arg0) {        // TODO Auto-generated method stub        threadstate = true;        mThread = new Thread(this);        mThread.start();    }    @Override    public void surfaceDestroyed(SurfaceHolder arg0) {        // TODO Auto-generated method stub        threadstate = false;    }     public void mDraw(){        Canvas canvas = holder.lockCanvas();        if (canvas != null) {            canvas.drawRGB(0, 0, 0);                canvas.drawText("HELLO SURFACEVIEW", x, y, paint);                canvas.drawCircle(x, y, setRadius(), paint);        }        holder.unlockCanvasAndPost(canvas);    }    private int setRadius(){        radius = (int)(Math.random()*20);        return radius;    }    @Override    public boolean onTouchEvent(MotionEvent event) {        // TODO Auto-generated method stub        x = (int)event.getX();        y = (int)event.getY();//        mDraw();        return true;    }    @Override    public void run() {        int X = 500;        // TODO Auto-generated method stub        while(threadstate){            long start = System.currentTimeMillis();            mDraw();            long end = System.currentTimeMillis();            try {                if ((end - start) < X) {                    Thread.sleep(X - (end - start));                }            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }        }

其中的setradius()方法是简单的实现了为绘制的园随机取半径大小,MainAcitivity.java的代码没有改变。
运行效果如下: