android群英传笔记 surfaceView

View通过刷新来重绘视图,android系统通过发出VSYNC信号来进行屏幕重绘,刷新间隔时间为16ms,如果在16ms内view完成了你所需要执行的所有操作,那么用户在视觉上就不会出现卡顿感觉,否则会导致画面卡顿。自定义view中经常会出现 The Application may be doing too munch work on its main thread 这样的警告日志。

这种警告的产生,多半是因为在绘制过程中处理逻辑太多造成的。

  SurfaceView 和View 的差别。

1.View 主要适应于主动更新的情况,而SurfaceView适应于被动更新,例如频繁的刷新。

2.View在主线程中对画面进行刷新,而SurfaceView通常会通过一个子线程进行页面的刷新。

3.View在绘图时没有使用双缓冲机制,而SurfaceView底层实现机制已经实现了双缓冲机制。

所以,如果你的自定义view需要频繁的刷新,或者刷新时数据处理量比较大,就考虑用SurfaceView.

示例一:一个自动的sin图像绘制

使用步骤:

1.创建一个类继承SurfaceView 然后实现SurfaceHolder.Callback和Runnable,重写相应的方法,添加构造函数。

2.定义全局变量 SurfaceHolder,Canvas,子线程标志位 isDrawing,画笔Paint,绘制路径Path.

3.定义一个方法初始化参数

4.定义一个draw()方法,通过surfaceholder.lockCanvas()获取一个canvas,通过canvas绘制想要绘制的view

5.在重写的run方法里通过调用draw方法进行绘制。

6.在surfaceCreated()方法里将子线程开启。将子线程标志位定义为true

7.在surfaceDestroyed()方法里将子线程标志位定义为false。

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private SurfaceHolder mHolder;
    //    用于绘制的canvas
    private Canvas mCanvas;
    //    子线程标志位
    private boolean mIsDrawing;
    private Path path;
    private Paint paint;

    public MySurfaceView(Context context) {
        super(context);
        initParams();

    }

    public MySurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initParams();

    }

    public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initParams();
    }


    private void initParams() {
//        SurfaceHolder
        mHolder = getHolder();
        mHolder.addCallback(this);

        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);

        path = new Path();
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.RED);
        paint.setStrokeWidth(10);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
    }


    /**
     * 开启子线程进行绘制
     *
     * @param surfaceHolder
     */
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        mIsDrawing = true;
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        mIsDrawing = false;

    }

    private int x = 0;
    private int y = 0;

    /* 子线程使用一个while(isDrawing)来循环不停的绘制
    * 通过lockCanvas来获取一个Canvas对象
    * 通过unlockCanvasAndPost(canvas)对画布内容进行提交。
    * 提交步骤最好放在finally,保证每次都能将内容提交。
    * */
    @Override
    public void run() {
        path.moveTo(0, 400);
        while (mIsDrawing) {
            draw();
            x += 1;
            y = (int) (100 * Math.sin(x * 2 * Math.PI / 180) + 400);
            path.lineTo(x, y);
        }
    }

    private void draw() {
        try {
//        获取一个canvas对象。注意,这里的canvas对象还是继续上次的canvas,之前的绘图操作都会保留,如果需要擦出,可以在绘制前
//        通过 canvas.drawColor()进行清屏操作。
//        canvas = mHolder.lockCanvas();
            mCanvas = mHolder.lockCanvas();
            mCanvas.drawColor(Color.WHITE);
            mCanvas.drawPath(path, paint);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (mCanvas != null) {
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    }
}

示例二,一个简易画板

public class DrawSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private SurfaceHolder mHolder;
    private boolean isDrawing;
    private Canvas canvas;
    private Path path;
    private Paint paint;

    public DrawSurfaceView(Context context) {
        super(context);
        initParams();
    }

    public DrawSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initParams();

    }

    public DrawSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initParams();

    }


    private void initParams() {
//      初始化SurfacHolder
        mHolder = getHolder();
        mHolder.addCallback(this);

        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);

        path = new Path();
        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10);

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path.moveTo(x, y);
                break;
            case MotionEvent.ACTION_MOVE:
                path.lineTo(x, y);
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }

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

    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        isDrawing = false;
    }

    @Override
    public void run() {
        long start = System.currentTimeMillis();
        while (isDrawing) {
            draw();
        }
        long end = System.currentTimeMillis();
        if (end - start < 100) {
            try {
                Thread.sleep(100 - (end - start));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void draw() {
        try {
            canvas = mHolder.lockCanvas();
            canvas.drawColor(Color.GREEN);
            canvas.drawPath(path, paint);

        } catch (Exception e) {

        } finally {
            if (canvas != null) {
                mHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值