正文  UI设计 > SurfaceView >

SurfaceView显示动画效果

一、基础知识:SurfaceView继承自View,View负责在主线程中更新动画,而SurfaceView是在一个新线程中更新动画。 SurfaceView类的主要方法:// 在Su...

一、基础知识:
SurfaceView继承自View,View负责在主线程中更新动画,而SurfaceView是在一个新线程中更新动画。
 
SurfaceView类的主要方法:
// 在SurfaceView创建时调用
pubilic abstract void surfaceCreated(SurfaceHolder holder)
// 在SurfaceView改变时调用
pubilic abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
// 在SurfaceView销毁时调用
pubilic abstract void surfaceDestroyed(SurfaceHolder holder)
// 绘制SurfaceView画面
protected void onDraw(Canvas canvas)
(参数canvas是该SurfaceView的画笔,每一次SurfaceView中画面改变都是调用了该方法)
 
二、实现效果:
首先有一副图片从屏幕的左下角开始向右上方运动,当图片上沿与手机屏幕上沿相撞时,图片的水平速度大小与方向均不变,竖直方向上速度大小不变,
方向相反;当下沿相撞后,同样效果,直到图片飞出屏幕。之后,屏幕渐渐地显示一幅图片。
 
三、编程实现:
1. 界面编辑(res\layout\main.xml):
[java]  
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    >  
<TextView    
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"   
    android:text="@string/hello"  
    />  
</LinearLayout>  
 
2. 代码编辑:
(\src\wyf\zcl\MyActivity.java)
[java] 
package wyf.zcl;  
/* 
 *  该例子演示surfaceView中简单场景的绘制 
 *  MyActivity.java     为程序的主Activity 
 *  MySurfaceView.java  为程序的SurfaceView类 
 *  Constant.java       常量类,将常量全部写在该类中 
 *  OnDrawThread.java   该类的作用是时时刷新onDraw,进行画面的重绘 
 *  PicRunThread.java   该类是控制duke图片运动的类 
 * */  
import android.app.Activity;                        //引入相关包  
import android.content.pm.ActivityInfo;             //引入相关包  
import android.os.Bundle;                           //引入相关包  
import android.view.Window;                         //引入相关包  
import android.view.WindowManager;                  //引入相关包   
public class MyActivity extends Activity {  
    /** Called when the activity is first created. */  
    private MySurfaceView msv;          //得到surfaceView的引用  
    @Override  
    public void onCreate(Bundle savedInstanceState) {   //Activity的生命周期函数,该函数是在程序创建时调用  
        super.onCreate(savedInstanceState);  
        msv=new MySurfaceView(MyActivity.this);         //实例化MySurfaceView的对象  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  //设置屏幕显示没有title栏   
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,    
                      WindowManager.LayoutParams.FLAG_FULLSCREEN);  //设置全屏  
        //设置只允许横屏  
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
        setContentView(msv);                            //设置Activity显示的内容为msv  
    }  
}  
 
(\src\wyf\zcl\Constant.java)
[java]  
package wyf.zcl;  
import android.view.Display;  
//Constant.java     常量类,将常量全部写在该类中  
public class Constant {  
    public static int SCREENWIDTH=480;  //屏幕宽(本程序为横屏)  
    public static int SCREENHEIGHT=320;     //屏幕高  
    public static int PICWIDTH=64;          //图片宽度  
    public static int PICHEIGHT=64;         //图片高度  
    public static int ONDRAWSPEED=30;       //onDraw线程类的绘制间隔时间  
    public static float PICXSPEED=1.5f;     //图片水平移动速度  
    public static float PICYSPEED=2;        //图片垂直移动速度  
    public static int PICRUNSPEED=30;       //图片的运动线程的刷新速度  
    public static int PICALPHASPEED=20; //图片渐暗效果演示刷新速度  
}  
 
(\src\wyf\zcl\MySurfaceView.java)
[java] 
package wyf.zcl;  
import android.content.Context;                 //引入相关包  
import android.graphics.Bitmap;                 //引入相关包  
import android.graphics.BitmapFactory;          //引入相关包  
import android.graphics.Canvas;                 //引入相关包  
import android.graphics.Color;                  //引入相关包  
import android.graphics.Paint;                  //引入相关包  
import android.view.Display;                    //引入相关包  
import android.view.SurfaceHolder;              //引入相关包  
import android.view.SurfaceView;                //引入相关包  
public class MySurfaceView extends SurfaceView  
implements SurfaceHolder.Callback{            
    //此处实现SurfaceHolder.Callback接口,为surfaceView添加生命周期回调函数  
    int dy=Display.DEFAULT_DISPLAY;  
    MyActivity ma;                          //得到MyActivity的引用  
    Paint paint;                            //画笔的引用  
    OnDrawThread odt;                       //OnDrawThread类引用  
    PicRunThread prt;                       //图片运动的Thread类引用  
    private float picX=0;                       //图片x坐标  
    private float picY=0;                       //图片y坐标  
    boolean picAlphaFlag=false;                 //图片变暗效果的标记,false为不显示,true为显示。  
    int picAlphaNum=0;                          //图片变暗效果中画笔的alpha值  
    public MySurfaceView(Context context) {  
        super(context);  
        this.ma=(MyActivity) context;             
        //将ma的引用指向调用了该Surfaceview类构造器方法的对象,本例为MyActivity  
        this.getHolder().addCallback(this);     //注册回调接口  
        paint=new Paint();                      //实例化画笔  
        odt=new OnDrawThread(this);             //实例化OnDrawThread类  
        prt=new PicRunThread(this);             //实例化PicRunThread类  
        prt.start();  
    }  
    public void setPicX(float picX) {           //图片x坐标的设置器  
        this.picX = picX;  
    }  
    public void setPicY(float picY) {           //图片y坐标的设置器  
        this.picY = picY;  
    }  
    public void setPicAlphaNum(int picAlphaNum) {//图片变暗效果alpha参数设置器  
        this.picAlphaNum = picAlphaNum;  
    }  
    @Override  
    protected void onDraw(Canvas canvas) {  //onDraw方法,此方法用于绘制图像,图形等  
        super.onDraw(canvas);  
        paint.setColor(Color.WHITE);        //设置画笔为白色  
        canvas.drawRect(0, 0, Constant.SCREENWIDTH, Constant.SCREENHEIGHT, paint);  
        //此处画了一个白色的全屏幕的矩形,目的是设置背景为白色,同时每次重绘时清除背景  
        //进行平面贴图  
        Bitmap bitmapDuke=BitmapFactory.decodeResource(ma.getResources(), R.drawable.duke);  
        canvas.drawBitmap(bitmapDuke, picX, picY, paint);  
        //图片渐暗效果  
        if(picAlphaFlag){  
            Bitmap bitmapBG=BitmapFactory.decodeResource(ma.getResources(), R.drawable.jpg1);  
            paint.setAlpha(picAlphaNum);  
            canvas.drawBitmap(bitmapBG, 0,0, paint);  
        }  
    }  
    @Override  
    public void surfaceChanged(SurfaceHolder holder, int format, int width,  
            int height) {           //此方法为当surfaceView改变时调用,如屏幕大小改变。  
    }  
    @Override  
    public void surfaceCreated(SurfaceHolder holder) {//此方法为在surfaceView创建时调用  
        odt.start();                //启动onDraw的绘制线程  
    }  
    @Override  
    public void surfaceDestroyed(SurfaceHolder holder) {//此方法为在surfaceView销毁前调用  
    }  
}  
 
(\src\wyf\zcl\OnDrawThread.java)
[java]  
package wyf.zcl;  
import android.graphics.Canvas;                 //引入相关包  
import android.view.SurfaceHolder;              //引入相关包  
//该类的作用是时时刷新onDraw,进行画面的重绘  
public class OnDrawThread extends Thread{  
    MySurfaceView msv;      //得到MySurfaceView的引用  
    SurfaceHolder sh;       //SurfaceHolder引用  
    public OnDrawThread(MySurfaceView msv) {  
        super();  
        this.msv = msv;         //构造方法中,将msv引用指向调用了该类的MySurfaceView的对象  
        sh=msv.getHolder();  
    }  
    @Override  
    public void run() {  
        super.run();  
        Canvas canvas = null;   //Canvas的引用  
        while(true){  
            try{  
                canvas=sh.lockCanvas(null);         //将canvas的引用指向surfaceView的canvas的对象  
                synchronized(this.sh){              //绘制过程,可能带来同步方面的问题,加锁  
                    if(canvas!=null){  
                    msv.onDraw(canvas);  
                    }  
                }  
            }finally{  
                try{  
                        if(sh!=null){  
                            sh.unlockCanvasAndPost(canvas); //绘制完后解锁  
                        }  
                }catch(Exception e){e.printStackTrace();}  
            }  
            try{  
                Thread.sleep(Constant.ONDRAWSPEED);                 //休息1秒钟  
            }catch(Exception e){e.printStackTrace();}  
        }  
    }  
}  
 
(\src\wyf\zcl\PicRunThread.java)
[java]  
package wyf.zcl;  
//该类是控制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-speed  
    int picAlphaNum=0;                  //图片变暗效果中画笔的alpha值  
    public PicRunThread(MySurfaceView msv) {  
        super();  
        this.msv = msv;         //将该线程类的引用指向调用其的MySurfaceView的对象  
    }  
    @Override  
    public 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=0;picAlphaNum<=255;picAlphaNum++){  
                if(picAlphaNum==255){  
                    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();}  
            }  
        }  
    }  
}  
 
这部分代码对于我这个初学java的人来说比较吃力,但是硬着头皮看了两天,还是基本弄清了这个框架。
代码中涉及一些java的基础知识,我做了一点笔记,如下:
 
[ extends ]:
一个类使用关键字extends继承其他类,关键字extends出现在类声明时的类名后,
extends后面跟着的是要继承的类的名称,extends实现了继承。在Java中的类只能继承一个类。
 
 
 
[ super ]:
B 继承 A ,B想调用A的方法,那么就可以 用super.A的方法。如果用中文解释:super就是父类的一个别名。
 
 
[ implements ]:
implements是一个类实现一个接口用的关键字,
他是用来实现接口中定义的抽象方法
。比如:people是一个接口,他里面有say这个方法。
public interface people()
{
   public say();
}
但是接口没有方法体。
只能通过一个具体的类去实现其中的方法体。
比如chinese这个类,就实现了people这个接口。
 public class chinese implements peopel{ 
   public say()
   {System.out.println("你好!");}
}
 
 
 
 
[ extends和implements区别]:
[plain] 
extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,  
JAVA中不支持多重继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,  
但implements可以实现多个接口,用逗号分开就行了   
比如   
class A extends B implements C,D,E