Android之SurfaceView的使用

使用的一些重点:
1.自定义一个View继承于SurfaceView并实现回调(Callback)和OntouchListener
2.自定义draw和clear方法,利用Paint和Path

public class MyView extends SurfaceView implements Callback, OnTouchListener{

    private Paint paint = new Paint();
    private Path path = new Path();

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        // 添加回调
        getHolder().addCallback(this);
        // 设置一定的属性
        paint.setColor(Color.RED);
        paint.setTextSize(10);
        paint.setStyle(Style.STROKE);
        paint.setAntiAlias(true);
        // 设置监听
        setOnTouchListener(this);
    }

    public void draw(){
         // 锁定画板
        Canvas canvas = getHolder().lockCanvas();
         // 进行一定的操作
        canvas.drawColor(Color.WHITE);
        canvas.drawPath(path, paint);
         // 解锁画板
        getHolder().unlockCanvasAndPost(canvas);
    }

    public void clear(){
        // 重置,记得调用回draw方法
        path.reset();
        draw();
    }

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

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub

    }

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

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            path.moveTo(event.getX(), event.getY());
            draw();
            break;

        case MotionEvent.ACTION_MOVE:
            path.lineTo(event.getX(), event.getY());
            draw();
            break;
        }
        return true;
    }

}

清除画板:
获得MyView实例后调用clear方法即可。

注意点:
1.关于canvas.save()和canvas.restore():
这里canvas.save();和canvas.restore();是两个相互匹配出现的,作用是用来保存画布的状态和取出保存的状态的。
当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响。

代码段1:

 public void draw() {   
      Canvas canvas = sfh.lockCanvas();    
      canvas.drawColor(Color.BLACK);  
      canvas.drawBitmap(bmp1, 0,0,paint);  
      canvas.save();   
      canvas.scale(5f, 5f);  
      canvas.restore();   
      canvas.drawBitmap(bmp2, 0,0,paint);  
      sfh.unlockCanvasAndPost(canvas);    
  }  

代码段2:

 public void draw() {   
      Canvas canvas = sfh.lockCanvas();    
      canvas.drawColor(Color.BLACK);  
      canvas.drawBitmap(bmp1, 0,0,paint);  
      canvas.scale(5f, 5f);  
      canvas.drawBitmap(bmp2, 0,0,paint);  
      sfh.unlockCanvasAndPost(canvas);    
 }  

上面这两个代码片段中我们都假设有两张图片bmp1和bmp2,并且都画在画布上!
那么代码段1和代码段2的不同:
代码段1中我们进行画布缩放的之前保存了画布状态,做了缩放操作之后又取出之前保存的状态,这样做是为了保证bmp2正常画出来不受到缩放的影响!
代码段2里,画了bmp1后就执行了缩放操作,并且没有保存状态!紧接着画了bmp2,那么bmp2也会一样受到缩放的影响!!
所以我们如果单独处理一张图片的时候,而且不想影响其他部分的绘制,那么应该如下来做:

    public void draw() {   
        Canvas canvas = sfh.lockCanvas();    
        canvas.drawColor(Color.BLACK);  
        canvas.drawBitmap(bmp1, 0,0,paint);  
        canvas.save();   
        canvas.scale(5f, 5f);  
        canvas.drawBitmap(bmp2, 0,0,paint);  
        canvas.restore();   
        sfh.unlockCanvasAndPost(canvas);    
    }

2.绘制多个图形并实现动画移动效果
a.可以先新建一个父类Container

 public class Container {

    private List<Container> children = null;
    private float x = 0;
    private float y = 0;

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

    public void childrenView(Canvas canvas) {
    };

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

    public void addChildrenView(Container child){
        children.add(child);
    }

    public void deleteChildrenView(Container child){
        children.remove(child);
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }
}

b.再建立两个子类继承此父类(以Rect和Circle为例)

public class Rect extends Container{

    private Paint paint = null;

    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);
        this.setY(this.getY() + 1);
    }
}

public class Circle extends Container{

    private Paint paint = null;

    public Circle() {
        paint = new Paint();
        paint.setColor(Color.BLUE);
    }

    @Override
    public void childrenView(Canvas canvas) {
        // TODO Auto-generated method stub
        super.childrenView(canvas);
        canvas.drawCircle(50, 50, 50, paint);
    }
}

c.实现效果

public class MyView extends SurfaceView implements SurfaceHolder.Callback{

    private Container container;
    private Rect rect;
    private Circle circle;

    public MyView(Context context) {
        super(context);
        container = new Container();
        rect = new Rect();
        circle = new Circle();
        rect.addChildrenView(circle);
        container.addChildrenView(rect);
        getHolder().addCallback(this);
    }

    public void draw(){
        Canvas canvas = getHolder().lockCanvas();
        canvas.drawColor(Color.WHITE);
        container.draw(canvas);
        getHolder().unlockCanvasAndPost(canvas);
    }

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

   // 实现移动效果
    public void startTimer(){
        timer = new Timer();
        task = new TimerTask() {

            @Override
            public void run() {
                draw();
            }
        };
        timer.schedule(task, 100, 100);
    }

    public void stopTimer(){
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        startTimer();   //必须在此处调用
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopTimer();    //必须在此处调用
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值