美文网首页
Android中SurfaceView的使用

Android中SurfaceView的使用

作者: baolvlv | 来源:发表于2017-09-01 16:06 被阅读0次

    SurfaceView是简单高效的用于渲染图形的类,适合用于简单的2D游戏开发。

    本文介绍了Android中SurfaceView的使用,包括使用SurfaceView绘制单个图形,多个图形,组合图形,并使组合图形移动。

    详细代码:github.com/Baolvlv/LearnAndroid/tree/master/SurfaceView

            surfaceView主要用于游戏开发,当view需要频繁绘制时,会消耗很多资源,这时可以使用surfaceview进行。同时surfaceviwe可以在主线程之外的线程中进行。当画面需要被动更新时(靠事件触发,例如棋牌类游戏),可以使用view,而需要主动更新时,则选择surfaceview

    1.SurfaceView的使用

    创建一个类继承自SurfaceViwe,并实现SurfaceHolder.Callback接口,实现构造函数与借口的三个方法

    publicMyView(Context context) {

    super(context);

    //添加回调函数

    getHolder().addCallback(this);

    }

    //surface创建时执行

    @Override

    public voidsurfaceCreated(SurfaceHolder holder) {

    }

    //surface改变时执行

    @Override

    public voidsurfaceChanged(SurfaceHolder holder, intformat, intwidth, intheight) {

    }

    //surface意外销毁时执行

    @Override

    public voidsurfaceDestroyed(SurfaceHolder holder) {

    }

    //创建画布,图形开始时锁定画布,图形结束后解锁画布

    Canvas canvas = getHolder().lockCanvas();

    getHolder().unlockCanvasAndPost(canvas);

    2.SurfaceView绘制单个图形

    声明化画笔,在构造方法中初始化并设置画笔颜色

    //声明画笔

    privatePaintpaint=null;

    paint=newPaint();

    paint.setColor(Color.RED);

    在自定义的Draw方法中,设置画布颜色并绘制图形

    public voiddraw(){

    //创建画布,图形开始时锁定画布,图形结束后解锁画布

    Canvas canvas = getHolder().lockCanvas();

    //设置画布颜色

    canvas.drawColor(Color.WHITE);

    //绘制长100宽100的矩形

    canvas.drawRect(0,0,100,100,paint);

    getHolder().unlockCanvasAndPost(canvas);

    }

    在surfaceCreate方法中调用绘制方法

    public voidsurfaceCreated(SurfaceHolder holder) {

    draw();

    }

    在MainActivity的onCreate方法中添加View

    setContentView(newMyView(this));

    3.SurfaceView绘制多个图形

    直接调用canvas不断绘制即可绘制多个图形

    当需要对其中的一个图形进行旋转,剪切等变换时,canvas.save与canvas.restore配合使用,用以不影响其他图形,旋转是通过旋转画布实现

    canvas.save();

    canvas.rotate(90,getWidth()/2,getHeight()/2);

    canvas.drawLine(0,getHeight()/2,getWidth(),getHeight(),paint);

    //还原画布

    canvas.restore();

    4.SurfaceView绘制组合图形

    绘制组合图形有三个要点:

    1.需要一个抽象的容器类,其子类为各种具体的图形,同时包含List储存各种子类图形

    2.画布在主SurfaceView中设置好后,在逐级容器间传递

    3.每个类得到画布后,绘制自己的图形

    步骤:

    自定义Container类,设置用于储存的List并在构造函数中初始化

    public classContanier {

    //储存子容器的List

    privateListchildren=null;

    //构造函数,实例化list

    publicContanier(){

    children=newArrayList();

    }

    编写向list中添加与删除view方法

    //添加子view方法

    public voidaddChildernView(Contanier child){

    children.add(child);

    }

    //移除子view方法

    public voidremoveChidernView(Contanier child){

    children.remove(child);

    }

    编写向子容器传递画布并绘制其独特图形的方法,之后在子容器中进行复写

    //向子容器传递画布并且子容器完成自己的绘制

    public voidchildernViewCanvasAndDraw(Canvas canvas){

    }

    编写向逐级子容器传递画布的方法

    //将画布传递给子容器,同时为容器内list中所有的子容器设置画布

    public voidsetCanvas(Canvas canvas){

    childernViewCanvasAndDraw(canvas);

    for(Contanier c :children){

    c.setCanvas(canvas);

    }

    编写具体图形类,继承自Contanier,作为容器可嵌套,构造函数初始化画笔

    public classRectextendsContanier{

    privatePaintpaint=null;

    //构造函数初始化画笔

    publicRect(){

    paint=newPaint();

    paint.setColor(Color.RED);

    }

    重写父类方法,接收画布绘制图形

    public voidchildernViewCanvasAndDraw(Canvas canvas){

    super.childernViewCanvasAndDraw(canvas);

    canvas.drawRect(0,0,100,100,paint);

    }

    主surfaceView构造函数中实例化contanier及具体图形

    privateContaniercontanier;

    privateRectrect;

    privateCirclecircle;

    contanier=newContanier();

    rect=newRect();

    circle=newCircle();

    rect.addChildernView(circle);

    contanier.addChildernView(rect);

    设置画布,并调用contanier类的方法传递画布

    //创建画布,图形开始时锁定画布,图形结束后解锁画布

    Canvas canvas = getHolder().lockCanvas();

    //设置画布颜色

    canvas.drawColor(Color.WHITE);

    //为所有容器统一设置画布

    contanier.setCanvas(canvas);

    getHolder().unlockCanvasAndPost(canvas);

    5.使组合图形移动

    通过x,y坐标完成移动,首先设置x,y坐标变量

    //设置坐标

    private floatx=0,y=0;

    get和set方法

    //get和set方法

    public voidsetX(floatx) {

    this.x= x;

    }

    public floatgetX() {

    returnx;

    }

    public voidsetY(floaty) {

    this.y= y;

    }

    public floatgetY() {

    returny;

    }

    在contanier类中为子容器逐级设置画布的方法中进行移动

    在canvas的save与restore方法中,进行画布移动

    /通过save和restore进行移动变化

    canvas.save();

    //根据当前的x,y坐标移动画布

    canvas.translate(getX(),getY());

    childernViewCanvasAndDraw(canvas);

    for(Contanier c :children){

    c.setCanvas(canvas);

    }

    canvas.restore();

    在最外层的矩形子类中,绘制图形后,当前纵坐标增加1,作为下一次绘制时的纵坐标,实现不断移动

    //不断增加画布移动坐标

    this.setY(getY() +1);

    在主surfaceView中,设置timer与timerTask,进行不断绘制

    //创建计时器与计时器任务对象

    privateTimertimer=null;

    privateTimerTasktask=null;

    //开始计时器方法

    public voidstartTimer(){

    timer=newTimer();

    task=newTimerTask() {

    //实例化timertask,复写run方法,不断进行绘制

    @Override

    public voidrun() {

    draw();

    }

    };

    //timer执行timerTask,100毫米后开始,每100毫秒执行一次

    timer.schedule(task,100,100);

    }

    //停止计时器

    public voidstopTimer(){

    //当计时器不为空时,取消计时器,并设置为空

    if(timer!=null){

    timer.cancel();

    timer=null;

    }

    在surfaceCreate方法中,开始计时器,在surfaceDestoryed方法中,停止计时器,否则会引发异常

    //surface创建时执行

    @Override

    public voidsurfaceCreated(SurfaceHolder holder) {

    startTimer();

    }

    //surface意外销毁时执行

    @Override

    public voidsurfaceDestroyed(SurfaceHolder holder) {

    //surface结束之后不停止timer,会出现异常

    stopTimer();

    }

    相关文章

      网友评论

          本文标题:Android中SurfaceView的使用

          本文链接:https://www.haomeiwen.com/subject/smkkjxtx.html