Android SurfaceView使用

与View区别

更新View任务太重会导致UI线程阻塞

而SurfaceView不会,可以在UI线程之外更新UI

 工程代码 SurfaceViewDemo.zip

----------------------------------------------

1. 使用SurfaceView 要点
2. 创建单个图形
3. 创建多个图形
4. 绘制组合图形
5. 使4中的组合图形动起来

----------------------------------------------

1. 使用SurfaceView 要点

* 通过 SurfaceHolder 控制Surface

* 一定是在Surface创建之后开始画布操作, 一定在Surface创建之前结束画布操作

 

集成 SurfaceView类,实现 SurfaceHolder.Callback 接口

在构造函数中调用: getHolder().addCallback(this);

框架如下:

public class MyView extends SurfaceView implements SurfaceHolder.Callback {
    // 通过 SurfaceHolder 控制Surface
    
    public MyView(Context context) {
        super(context);
        getHolder().addCallback(this);
    }
    public void draw() {
        // 一定是在Surface创建之后开始画布操作
        Canvas canvas = getHolder().lockCanvas();
        // start
        
        // end, 一定在Surface创建之前结束画布操作
        getHolder().unlockCanvasAndPost(canvas);
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // Surface 改变的时候触发
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        draw();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    }
}

 

2. 创建单个图形

修改如下,声明画笔 paint, 然后画一个红色的矩形

private Paint paint = null;

public MyView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
    paint = new Paint();
    paint.setColor(Color.RED);
    getHolder().addCallback(this);
}
public void draw() {
    // 一定是在Surface创建之后开始画布操作
    Canvas canvas = getHolder().lockCanvas();
    // start
    canvas.drawColor(Color.WHITE);
    canvas.drawRect(0, 0, 100, 100, paint);
    
    // end, 一定在Surface创建之前结束画布操作
    getHolder().unlockCanvasAndPost(canvas);
}

 

3. 创建多个图形

绘制两条垂直90度的直线,三个重要的步骤

canvas.save();// 保存成可编辑状态
canvas.rotate(90, getWidth()/2, getHeight()/2);  //画布旋转90度
canvas.restore(); //重新恢复画布到正常状态(旋转前),否则影响后面的绘制

public void draw() {
    // 一定是在Surface创建之后开始画布操作
    Canvas canvas = getHolder().lockCanvas();
    // start
    canvas.drawColor(Color.WHITE);
    canvas.save();// 保存成可编辑状态
    canvas.rotate(90, getWidth()/2, getHeight()/2);  //画布旋转90度
    canvas.drawLine(0, getHeight()/2, getWidth(), getHeight(), paint);
    canvas.restore(); //重新恢复画布到正常状态(旋转前)
    canvas.drawLine(0, getHeight()/2 + 100, getWidth(), getHeight()+100, paint);
    // end, 一定在Surface创建之前结束画布操作
    getHolder().unlockCanvasAndPost(canvas);
}

 

 

4. 绘制组合图形

 创建容器 Container 类: 可以添加、删除子视图, 绘制view

创一个矩形Rec:

创建 圆 Circle:

在控件MyView中,添加一个容器,容器中放置一个矩形,矩形内放一个圆

public class Container {

    private List<Container> children = null;

    public Container() {
        children = new ArrayList<Container>();
    }

    public void draw(Canvas canvas) {
        childrenView(canvas);
        for (Container c : children) {
            c.draw(canvas);
        }
    }

    public void addChirdrenView(Container c) {
        children.add(c);
    }

    public void removeChirdrenView(Container c) {
        children.remove(c);
    }

    public void childrenView(Canvas canvas) {
        // TODO Auto-generated method stub
    }
}
public class Rect extends Container {

    private Paint paint;
        
    public Rect(){
        paint = new Paint();
        paint.setColor(Color.RED);
    }
    
    @Override
    public void childrenView(Canvas canvas) {
        super.childrenView(canvas);
        canvas.drawRect(0, 0, 100, 100, paint);
    }
}
public class Circle extends Container {
    
    private Paint paint;
    
    public Circle(){
        paint = new Paint();
        paint.setColor(Color.BLUE);
    }

    @Override
    public void childrenView(Canvas canvas) {
        // 
        super.childrenView(canvas);
        canvas.drawCircle(60, 60, 50, paint);
    }
}
public class MyView extends SurfaceView implements SurfaceHolder.Callback {
    // 通过 SurfaceHolder 控制Surface
    
    private Container container;
    private Rect rect;
    private Circle circle;

    public MyView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        container = new Container();
        rect = new Rect();
        circle = new Circle();
        rect.addChirdrenView(circle);
        container.addChirdrenView(rect);
        
        getHolder().addCallback(this);
    }
    
    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // Surface 改变的时候触发
        draw() ;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    }
    
    public void draw() {
        // 一定是在Surface创建之后开始画布操作
        Canvas canvas = getHolder().lockCanvas();
        // start
        canvas.drawColor(Color.WHITE);
        container.draw(canvas);
        // end, 一定在Surface创建之前结束画布操作
        getHolder().unlockCanvasAndPost(canvas);
    }

}

5. 使4中的组合图形动起来

修改容器类Container:

public void draw(Canvas canvas) {
    canvas.save();
    canvas.translate(getX(), getY());
    childrenView(canvas);
    for (Container c : children) {
        c.draw(canvas);
    }
    canvas.restore();
}

修改矩形:

public void childrenView(Canvas canvas) {
    super.childrenView(canvas);
    canvas.drawRect(0, 0, 100, 100, paint);
    
    this.setY(this.getY()+3);
}

在 MyView 控件中增加timer

private Timer timer = null;
private TimerTask task = null;

public void startTimer(){
    timer = new Timer();
    task = new TimerTask() {
        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            draw();
        }
    };
    timer.schedule(task, 100, 100); //每100ms执行一次
}

public void stopTimer(){
    if (timer != null) {
        timer.cancel();
        timer = null;
    }
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
    // surface 创建之后
    startTimer();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // surface 销毁之前
    stopTimer();
}

@Override
protected void onDetachedFromWindow() {
    // TODO Auto-generated method stub
    stopTimer();  //不加这句,应用程序退出时会死
    super.onDetachedFromWindow();
}

工程代码 SurfaceViewDemo.zip

 

posted @ 2015-08-12 13:46  carlo-z  阅读(618)  评论(0编辑  收藏  举报