Android开发学习SurfaceView显示动画效果

一、基础知识:
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):
?
1
2
3
4
5
6
7
8
9
10
11
12
13
     
     <?xml version= "1.0"  encoding= "utf-8" ?>
<LinearLayout xmlns:<a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>= "http://schemas.<a title=" android " href=" http://www.android-study.com/jichuzhishi/ 543 .html ">android</a>.com/apk/res/<a title=" android " href=" http://www.android-study.com/jichuzhishi/ 543 .html ">android</a>"
     <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>:orientation= "vertical"
     <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>:layout_width= "fill_parent"
     <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>:layout_height= "fill_parent"
     >
<TextView 
     <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>:layout_width= "fill_parent"
     <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>:layout_height= "wrap_content"
     <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>:text= "@string/hello"
     />
</LinearLayout>

 

2. 代码编辑:
(\src\wyf\zcl\MyActivity.java)
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
         
     package  wyf.zcl;
/*
  *  该例子演示surfaceView中简单场景的绘制
  *  MyActivity.java     为程序的主Activity
  *  MySurfaceView.java  为程序的SurfaceView类
  *  Constant.java       常量类,将常量全部写在该类中
  *  OnDrawThread.java   该类的作用是时时刷新onDraw,进行画面的重绘
  *  PicRunThread.java   该类是控制duke图片运动的类
  * */
import <a title="android" href="http://www.android-study.com/jichuzhishi/543.html">android</a>.app.Activity;                        //引入相关包
import <a title="android" href="http://www.android-study.com/jichuzhishi/543.html">android</a>.content.pm.ActivityInfo;             //引入相关包
import <a title="android" href="http://www.android-study.com/jichuzhishi/543.html">android</a>.os.Bundle;                           //引入相关包
import <a title="android" href="http://www.android-study.com/jichuzhishi/543.html">android</a>.view.Window;                         //引入相关包
import <a title="android" href="http://www.android-study.com/jichuzhishi/543.html">android</a>.view.WindowManager;                  //引入相关包
public class MyActivity <a title="extends" href="http://www.android-study.com/jichuzhishi/543.html">extends</a> 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)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
     
     package  wyf.zcl;
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.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)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
         
     package  wyf.zcl;
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.content.Context;                 //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.graphics.Bitmap;                 //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.graphics.BitmapFactory;          //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.graphics.Canvas;                 //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.graphics.Color;                  //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.graphics.Paint;                  //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.view.Display;                    //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.view.SurfaceHolder;              //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.view.SurfaceView;                //引入相关包
public  class  MySurfaceView <a title= "extends"  href= "http://www.android-study.com/jichuzhishi/543.html" > extends </a> SurfaceView
<a title= "implements"  href= "http://www.android-study.com/jichuzhishi/543.html" > implements </a> 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  <a title= "surfaceCreated"  href= "http://www.android-study.com/jichuzhishi/543.html" >surfaceCreated</a>(SurfaceHolder holder) {//此方法为在surfaceView创建时调用
         odt.start();                 //启动onDraw的绘制线程
     }
     @Override
     public  void  surfaceDestroyed(SurfaceHolder holder) { //此方法为在surfaceView销毁前调用
     }
}

(\src\wyf\zcl\OnDrawThread.java)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
         
     package  wyf.zcl;
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.graphics.Canvas;                 //引入相关包
import  <a title= "android"  href= "http://www.android-study.com/jichuzhishi/543.html" >android</a>.view.SurfaceHolder;              //引入相关包
//该类的作用是时时刷新onDraw,进行画面的重绘
public  class  OnDrawThread <a title= "extends"  href= "http://www.android-study.com/jichuzhishi/543.html" > extends </a> 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)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
     
     package  wyf.zcl;
//该类是控制duke图片运动的类
public  class  PicRunThread <a title= "extends"  href= "http://www.android-study.com/jichuzhishi/543.html" > extends </a> 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区别]:
?
1
2
3
4
5
6
         
     <a title= "extends"  href= "http://www.android-study.com/jichuzhishi/543.html" > extends </a>是继承父类,只要那个类不是声明为 final 或者那个类定义为 abstract 的就能继承,
JAVA中不支持多重继承,但是可以用接口来实现,这样就要用到<a title= "implements" href= "http://www.android-study.com/jichuzhishi/543.html" > implements </a>,继承只能继承一个类,
但<a title= "implements"  href= "http://www.android-study.com/jichuzhishi/543.html" > implements </a>可以实现多个接口,用逗号分开就行了
比如
class  A <a title= "extends"  href= "http://www.android-study.com/jichuzhishi/543.html" > extends </a> B <a title= "implements" href= "http://www.android-study.com/jichuzhishi/543.html" > implements </a> C,D,E

你可能感兴趣的:(Android开发学习SurfaceView显示动画效果)