要自定义一个surfaceView首先就要继承 SurfaceView类并实现SurfaceHolder.Callback接口
那么什么是接口回调呢?
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
要实现下面的三个生命周期回调函数才能完整实现一个SurfaceView
三个重要的生命周期回调函数:
1.public abstract void surfaceCreated(SurfaceHolder holder)在SurfaceView创建时调用该函数。
2.public abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height),在SurfaceView改变时调用该函数。
3.public abstract void surfaceDestroyed(SurfaceHolder holder)在SurfaceView销毁前调用该函数。
SurfaceView中最重要的方法应该是protected void onDraw(Canvas canvas),它是用来绘制SurfaceView画面的,其中的参数canvas 是该SurfaceView的画笔。每一 次SurfaceView中画面的改变都是调用了该方法。
通常方法是:新建一个线程类,每隔一个周期用一次SurfaceViewdeOnDraw()方法,而OnDraw()方法中的画面也有一个线程在时时改变,这样后一个线程类实 现了OnDraw()画面中显示内容的变化,前一个线程类时时刷新画面,这就形成了动画。
不过在实现onDraw()函数却提示错误:Suspicious method call; should probably call "draw" rather than "onDraw",Google一下,改名为fix_onDraw()就可 以了,也许是有同名的函数。有待研究
SurfaceHolder:
public interface SurfaceHolder
显示一个surface的抽象接口,使你可以控制surface的大小和格式, 以及在surface上编辑像素,和监视surace的改变。
这个接口通常通过SurfaceView类实现
surface的控制器,用来操纵surface,处理它的Canvas上画的效果和动画,控制表面,大小,像素等。
几个需要注意的方法:
(1)、abstract void addCallback(SurfaceHolder.Callback callback);
// 给SurfaceView当前的持有者一个回调对象。
(2)、abstract Canvas lockCanvas();
// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
(3)、abstract Canvas lockCanvas(Rect dirty);
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
// 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。
(4)、abstract void unlockCanvasAndPost(Canvas canvas);
// 结束锁定画图,并提交改变。
SurfaceHolder.Callback:
用户可以实现此接口接收surface变化的消息。当用在一个SurfaceView 中时, 它只在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()之间有效。设置Callback的方法是SurfaceHolder.addCallback.
下面附上渐变的欢迎界面的SurfaceView实现的代码:
1 package com.example.mytafanggame; 2 3 import android.view.SurfaceView; 4 import android.view.SurfaceHolder; 5 import android.graphics.BitmapFactory; 6 import android.graphics.Color; 7 import android.graphics.Paint; 8 import android.graphics.Bitmap; 9 import android.graphics.Canvas; 10 11 public class WelcomeView extends SurfaceView implements SurfaceHolder.Callback{ 12 MyGameActivity activity; 13 Paint paint; 14 int currentAlpha = 0; //当前的不透明值 15 float screenWidth = Constant.SCREEN_HEIGHT; //屏幕宽度 16 float screenHeight = Constant.SCREEN_WIDTH; //屏幕高度 17 int sleepSpan = 50; //动画延时 18 Bitmap[] logos = new Bitmap[2]; //logo图片 19 Bitmap currentLogo; //当前图片 20 int currentX; 21 int currentY; 22 23 public WelcomeView(MyGameActivity activity){ 24 super(activity); 25 this.activity = activity; 26 this.getHolder().addCallback(this); //创建生命周期回调接口的实现 27 paint = new Paint(); //创建画笔 28 paint.setAntiAlias(true); //打开抗锯齿 29 logos[0] = BitmapFactory.decodeResource(activity.getResources(), R.drawable.dukea); 30 logos[1] = BitmapFactory.decodeResource(activity.getResources(), R.drawable.welcome); 31 } 32 33 public void fix_onDraw(Canvas canvas){ 34 paint.setColor(Color.BLACK); 35 paint.setAlpha(255); //设置可见度 36 canvas.drawRect(0, 0,screenWidth,screenHeight,paint); 37 if(currentLogo == null) 38 return; 39 paint.setAlpha(currentAlpha); //设置可见度 40 canvas.drawBitmap(currentLogo, currentX, currentY,paint); 41 } 42 43 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3){} 44 public void surfaceCreated(SurfaceHolder holder){ 45 new Thread(){ 46 public void run(){ 47 for(Bitmap bm:logos){ 48 currentLogo = bm; 49 currentX = activity.screenWidth/2 - bm.getWidth()/2; //绘制屏幕左边开始 50 currentY = activity.screenHeight/2 - bm.getHeight()/2; //绘制屏幕上边开始 51 for(int i=255; i>-10; i=i-10){ //不同透明度重复绘制 52 currentAlpha = i; 53 if(currentAlpha < 0){ //透明度为负数置为0 54 currentAlpha = 0; 55 } 56 SurfaceHolder myholder = WelcomeView.this.getHolder();//获取surfaceHolder 57 Canvas canvas = myholder.lockCanvas(); //锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了 58 try { 59 synchronized(myholder){ //同步锁,一个时间内只有一个线程能执行下面代码块 60 fix_onDraw(canvas); //绘制 61 } 62 } 63 catch (Exception e){ 64 e.printStackTrace(); 65 } 66 finally { 67 if(canvas != null){ 68 myholder.unlockCanvasAndPost(canvas); //结束锁定画图,并提交改变 69 } 70 } 71 try { 72 if(i == 255){ 73 Thread.sleep(1000); 74 } 75 Thread.sleep(sleepSpan); 76 } 77 catch (Exception e){ 78 e.printStackTrace(); 79 } 80 } 81 } 82 activity.sendMessage(1); 83 } 84 }.start(); 85 } 86 public void surfaceDestroyed(SurfaceHolder arg0){} 87 88 }