【Android 笔记】SurfaceView 的使用

Author Avatar
vecrates 12月 14, 2017

 SurfaceView 也是 View 的一种,但它可以在非 UI 线程显示、更新等。所以可以用它来完成一些绘制复杂、更新频繁的 UI(如游戏)。

######区别于 View 的特点

  • View 使用与主动更新,SurfaceView 使用于被动更新
  • View 运行与 UI 线程,SurfaceView 运行于子线程
  • SurfaceView 运用了双缓冲机制
Demo

 完成一个使用 SurfaceView 的绘图板。

步骤

1)继承 SurfaceView,实现 SurfaceViewHolder.Callback 和 Runnable:Callback.surfaceCreated() 开启线程;Runnable.run() 中调用绘制方法
2)初始化成员变量:SurfaceHolder、Canvas、boolean(线程标志位)
3)编写绘制逻辑:绘制前 lockCanvas,绘制完成 unlockCanvasAndPost

代码:

public class SurfaceViewTest extends SurfaceView implements SurfaceHolder.Callback, Runnable{

    private SurfaceHolder mHolder;
    private Canvas mCanvas;
    private Paint mPaint;
    private boolean isDraw; //子线程标识

    private Path mPath;

    public SurfaceViewTest(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mHolder = getHolder();
        mHolder.addCallback(this);
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);
        mPaint.setColor(Color.BLACK);
        setFocusable(true);
        mPath = new Path();
    }


    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        isDraw = true;
        new Thread(this).start();
    }

    //Surface大小格式改变时
    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        isDraw = false;
        mHolder.removeCallback(this);
    }

    @Override
    public void run() {
        while (isDraw) {
            synchronized (mHolder) {
                draw();
                try {
                    Thread.currentThread().sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @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;
    }

    //绘图逻辑
    private void draw() {
        try {
            mCanvas = mHolder.lockCanvas();
            if(mCanvas != null) {
                //设置画布颜色
                mCanvas.drawColor(Color.WHITE);
                mCanvas.drawPath(mPath, mPaint);
            }
        } finally {
            if(mCanvas != null) {
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }

    }

5892091-59fc8d6e0e184b83