SurfaceView有个很大的好处,就是可以在子线程中绘制UI,其他的View只能在主线程中更新UI,这或多或少给编程增加了些不便。而SurfaceVIew在子线程中可以绘制UI的特性,再加上其可以直接从内存或者DMA等硬件接口取得图像数据,这使得它适合2d游戏的开发。
SurfaceView使用步骤
SurfaceView的使用比较简单,可以总结为如下几个步骤:
1.继承SurfaceView并实现 SurfaceHolder.Callback方法
譬如:
public class StartAniSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
2.给SurfaceHolder对象注册回调方法
getHolder().addCallback(this);
SurfaceView中有个SurfaceHolder 的实例,这个实例是整个SurfaceView的核心,我们这个给这个SurfaceHolder实力添加回掉方法以后,就会导致surfaceCreated方法被回掉,用来通知你Surface已经准备好了,你可以绘图了。当你修改了SurfaceView的大小以后,surfaceChanged方法就会被会调,用来通知你Surface发生了改变,当你按下退出键,导致SurfaceView销毁的之前,surfaceDestroyed方法就会被调用,通知你Surface要销毁了,你赶紧手动释放需要释放的资源吧等等。
总之,addCallback这份方法一定要调用,不然回掉方法没有添加进去,就不可能有有毁掉方法调用的行为了。
3.在surfaceCreated方法中开始绘画
一般我们会在surfaceCreated方法中开启一个线程,让它来执行绘画的工作,当然不开启也没关系,直接绘画也可以。
准备好SurfaceView以后,SurfaceView的使用和其他的View就没有社么不同了,同门可以静态的在布局文件中使用,然后使用findViewById来获取到它的实例,也可以动态使用,直接new就可以了,相比也没什么好说的呢。
4.置顶、透明与清屏
SurfaceView如果希望在一副背景上运行动画,就要求SurfaceView是透明的,同时也是置顶的。这个时候,更新动画的时候,每次都要清屏,清屏操作也需要注意。以下是实现这三点的code:
置顶
setZOrderOnTop(true);
透明
holder.setFormat(PixelFormat.TRANSPARENT);
清屏
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
绘图
关于绘图,需要使用至少两个类:Canvas,和Paint,Paint可以理解成一个画笔,你在绘画前需要设置它的颜色,粗细等信息,Canvas可以理解成一个人,他手里拿着Paint,而且他有很多的技能,比如绘制矩形,椭圆等。我们说SurfaceView的核心是一个SurfaceHolder,所以,这个我们要绘图的话得有专业的画家,这个画家得向SurfaceHolder来要,它要是不给那就没办法了。因此,绘图的代码可以是这样:
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.WHITE);
paint.setColor(bgColor);
canvas.drawRoundRect(0,0,getWidth(),getHeight(),cornerRadius,cornerRadius,paint);
。。。
holder.unlockCanvasAndPost(canvas);
可以看到我们首先向holder请求一个画家canvas,canvas会使用paint来绘画,画好以后化一定要交给画家的boss,也就是holder,使用holder.unlockCanvasAndPost(canvas);来实现,这样这幅画才能显示出来。
动画就是不断的这样话一幅又一幅的画,只不过这些画前后有联系,这样就能形成动画。
游戏的启动动画
下面以2048游戏的启动动画为例,具体介绍SurfaceView的使用。
在2048游戏的启动动画中,就是使用了SurfaceView来绘制动画的,这里再把效果图拿出来:
这个动画模仿了焰火的效果,实现过程如下:
FlyNumber
一个飞出去的数字用FlyNumber类来表示,她的定义如下:
public class FlyNumber {
public Point start;
public Point control;
public Point end;
public Point cur;
public float t;
public int number;
public int clolor;
public int textSize;
public FlyNumber(){
start = new Point();
control = new Point();
end =