SurfaceView与View作用一样都是绘制控件,不同点是View是按照系统速率进行绘制,无法修改,而且是再UI线程中绘制的。而SurfaceView是在子线程中绘制的,可以修改绘制速率。
自定义SurfaceView的用法基本可以套用,基础实现公式是:
1.先创建自定义的View 继承SurfaceView ,实现SurfaceHolder.Callback和Runnable;
2.实现构造方法和接口的方法
3.定义SurfaceHolder,Canvas,isCanvas,Paint;
4.初始化SurfaceHolder、Paint;
5.在surfaceCreated方法中设置isCanvas=true;、开启一个线程;
6.在run方法中判断isCanvas是否为true,进行绘制
7.在绘制过程中获取canvas对象锁定画布,进行canvas绘制,通过try\catch,在finally方法中判断canvas是否为空,不为空进行解除画布锁定
8.在surfaceDestory方法中设置isCanvas=false;
public class MyDrawingBoard extends SurfaceView implements SurfaceHolder.Callback, Runnable { private SurfaceHolder mHolder; private Canvas mCanvas; private boolean isCanvas = false; private Paint mPaint; public MyDrawingBoard(Context context) { super(context); init(); } public MyDrawingBoard(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MyDrawingBoard(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mHolder = getHolder(); mHolder.addCallback(this); mPaint=new Paint(); mPaint.setStrokeWidth(3); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.BLUE); } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { isCanvas = true; new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { isCanvas = false; } @Override public void run() { while (isCanvas) { draw(); } } private void draw() { try { mCanvas=mHolder.lockCanvas(); //mCanvas do something 绘制操作 }catch (Exception e){ }finally { if(mCanvas!=null) mHolder.unlockCanvasAndPost(mCanvas); } } }
示例:
这是一个实现画板的小例子:
public class MyDrawingBoard extends SurfaceView implements SurfaceHolder.Callback, Runnable { private SurfaceHolder mHolder; private Canvas mCanvas; private boolean isCanvas = false; private Path mPath; private Paint mPaint; public MyDrawingBoard(Context context) { super(context); init(); } public MyDrawingBoard(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MyDrawingBoard(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mHolder = getHolder(); mHolder.addCallback(this); mPath=new Path(); mPaint=new Paint(); mPaint.setStrokeWidth(3); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.BLUE); } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { isCanvas = true; new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { isCanvas = false; } @Override public void run() { while (isCanvas) { draw(); } } private void draw() { try { mCanvas=mHolder.lockCanvas(); mCanvas.drawColor(Color.GRAY); mCanvas.drawPath(mPath,mPaint); }catch (Exception e){ }finally { if(mCanvas!=null) mHolder.unlockCanvasAndPost(mCanvas); } } @Override public boolean onTouchEvent(MotionEvent event) { int x= (int) event.getX(); int y= (int) event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: mPath.moveTo(x,y); break; case MotionEvent.ACTION_MOVE: mPath.lineTo(x,y); break; } return true; } }