Android開發之SurfaceView顯示動畫效果

來源:互聯網
上載者:User

  一、基礎知識:

  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. 介面編輯(reslayoutmain.xml):

  [java]

  

  android:orientation="vertical"

  android:layout_width="fill_parent"

  android:layout_height="fill_parent"

  >

  

  android:layout_width="fill_parent"

  android:layout_height="wrap_content"

  android:text="@string/hello"

  />

  

  

  android:orientation="vertical"

  android:layout_width="fill_parent"

  android:layout_height="fill_parent"

  >

  

  android:layout_width="fill_parent"

  android:layout_height="wrap_content"

  android:text="@string/hello"

  />

  

  2. 代碼編輯:

  (srcwyfzclMyActivity.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

  }

  }

  (srcwyfzclConstant.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; //圖片漸暗效果示範重新整理速度

  }

  (srcwyfzclMySurfaceView.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銷毀前調用

  }

  }

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

  }

  }

  }

  (srcwyfzclPicRunThread.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

  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

  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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.