关于SurfaceView

来源:互联网 发布:js调用api接口代码 编辑:程序博客网 时间:2024/06/02 02:12
SurfaceView 是在子线程中更新画面的组件, View是 在 UI 的主线程中更新画面, 适合于做动画.
使用SurfaceView 通常要实现 SurfaceHolder.Callback接口,SurfaceView 类的生命周期有3个回调函数,分别为:
public abstract  void surfaceCreated(SurfaceHolder holder) 在SurfaceView 创建时调用
public abstract  void surfaceChanged(SurfaceHolder  holder,  int  format,  int width,  int height) 在SurfaceView 改变时调用
public  abstract  void surfaceDestroyed(SurfaceHolder  holder)在SurfaceView 销毁前调用

此外, 还有一个重要方法:
protected void  onDraw(Canvas c)  用来绘制SurfaceView 画面, 每一次SurfaceView  中画面改变都是调用此方法.
通常实现动画效果原理是:
新建一个线程类,每隔一段时间调用SurfaceView 的onDraw(), 在onDraw() 方法中的画面也有一个线程类在时刻改变,这样后一个线程类实现了onDraw() 画面中显示内容的变化, 前一个线程类 时刻刷新画面,这样就形成了动画.
具体代码请参见 SufaceView_3_7 工程, 讲解一下两个线程类
public class OnDrawThread extends Thread {MySurfaceView msv; // 得到MySurfaceView的引用SurfaceHolder sh; // SurfaceHolder引用public OnDrawThread(MySurfaceView msv) {  super();  this.msv = msv; // 构造方法中,将msv引用指向调用了该类的MySurfaceView的对象  sh = msv.getHolder();}@Overridepublic void run() {  super.run();  Canvas canvas = null;   while (true) {   // 这个循环用于时刻刷新界面   try {    canvas = sh.lockCanvas(null); // 将canvas的引用指向surfaceView的canvas的对象    synchronized (this.sh) { // 绘制过程,可能带来同步方面的问题,加锁     if (canvas != null) {      msv.onDraw(canvas);    // 这里调用onDraw(),时刻刷新画面     }    }   } finally {    try {     if (sh != null) {      sh.unlockCanvasAndPost(canvas); // 绘制完后解锁     }    } catch (Exception e) {     e.printStackTrace();    }   }try {    Thread.sleep(Constant.ONDRAWSPEED); // 休息1秒钟   } catch (Exception e) {    e.printStackTrace();   }  }}}----------------------------------//该类是控制duke图片运动的类public class PicRunThread extends Thread{MySurfaceView msv;         //MySurfaceView的引用private float picX=0;   //图片x坐标private float picY=Constant.SCREENHEIGHT-Constant.PICHEIGHT;   //图片y坐标boolean yRunFlag=false;  //y方向上的运动标记,false时y=y+speed,true时y=y-speedint picAlphaNum=0;     //图片变暗效果中画笔的alpha值public PicRunThread(MySurfaceView msv) {  super();  this.msv = msv;   //将该线程类的引用指向调用其的MySurfaceView的对象}@Overridepublic void run() {  super.run();  while(true){             //这个循环用于显示内容变化,实现重复显示,  如果没有则画面只显示一遍   //控制duke图片的运动   while(this.picX<Constant.SCREENWIDTH){   //当图片的左边完全超过屏幕的右边时,循环结束    msv.setPicX(picX);    msv.setPicY(picY);    picX=picX+Constant.PICXSPEED;    if(yRunFlag){//应该向上运动,自减     picY=picY-Constant.PICYSPEED;    }else{//应该向下运动,自加     picY=picY+Constant.PICYSPEED;    }    if(picY<=0){         //到达屏幕上沿     yRunFlag=false;    }else if(picY>Constant.SCREENHEIGHT-Constant.PICHEIGHT){  //到达屏幕下沿yRunFlag=true;    }    try{     Thread.sleep(Constant.PICRUNSPEED);    }catch(Exception e){e.printStackTrace();}   }   //图片变暗效果演示   msv.picAlphaFlag=true;       //开启图片变暗效果   for(picAlphaNum=100;picAlphaNum<=200;picAlphaNum++){    if(picAlphaNum==200){     msv.picAlphaFlag=false;     //当图片变暗效果结束,标记重置     picX=0;   //图片x坐标     picY=Constant.SCREENHEIGHT-Constant.PICHEIGHT;   //图片y坐标     System.out.println(msv.picAlphaFlag+"picX:"+picX+"picY:"+picY);    }    msv.setPicAlphaNum(picAlphaNum);    try{     Thread.sleep(Constant.PICALPHASPEED);    }catch(Exception e){e.printStackTrace();}   }  }}}

效果图示意如下:

原创粉丝点击