Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android開發學習08]SurfaceView顯示動畫效果

[Android開發學習08]SurfaceView顯示動畫效果

編輯:關於Android編程

一、基礎知識:

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> 

<?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  
    } 

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; //圖片漸暗效果演示刷新速度  

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銷毀前調用  
    } 

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();} 
        } 
    } 

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();} 
            } 
        } 
    } 

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 

extends是繼承父類,只要那個類不是聲明為final或者那個類定義為abstract的就能繼承,
JAVA中不支持多重繼承,但是可以用接口來實現,這樣就要用到implements,繼承只能繼承一個類,
但implements可以實現多個接口,用逗號分開就行了
比如
class A extends B implements C,D,E

 

 


 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved