Internship 8th day: Use Android-Tween Animation in SurfaceView!

Original address: http://blog.csdn.net/xiaominghimi/article/details/6116089

Li Huaming HimiOriginal, reprint must be clearly noted:

Reprinted from [Black Rice GameDev Block] Original link: http://www.himigame.com/android-game/331.html

< p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial; fo nt-size:14px; line-height:26px"> Many children’s shoes say that after my code runs, the program will be abnormal after clicking home or back If you have encountered this, then you must have not read Himi’s blog carefully. The nineteenth article Himi specifically wrote about the causes and solutions of these errors, here I am adding to the blog, the children’s shoes of the province I’m always confused about this one; please click on the link below to read it:

【Android Game Development Nineteen】( Must-see article) Detailed explanation of the operating mechanism of SurfaceView—Analyze the Back and Home buttons and cut into the background and other exception handling!

In [Android2D Game Development IV], I introduced a 13-frame png image to you, using the method of setting the visible area to achieve the animation effect, but these It belongs to our own way of implementing animation. In fact, Android gives us two types of custom animation methods:

Type 1: Frame By Frame animation (not recommended for game development)

The so-called frame animation is to play pre-made images in sequence, similar to playing a movie;

Analysis: This method is similar to the way I used to set the visible area to achieve the animation effect, not only similar but also Not as good! So this method will not be analyzed here;

The second category: Tween Animation gradient animation

, that is, through continuous image transformation of the object( Pan, zoom, rotate) to produce animation effects! The realization method is actually to predefine a set of instructions, which specify the type, trigger time, and duration of the graphics transformation. These instructions can be defined in the form of XML files, or they can be defined in the form of source code. The program executes these instructions along the timeline to achieve the animation effect.

Summary: So in Android game development, we prefer to use two methods: The first method is to set the visible area to achieve the animation effect (frame animation), which needs to be implemented manually by children’s shoes. Then I have the corresponding source code in my previous blog post [Android2D Game Development IV]! You can download and study; then, here is a detailed analysis of Tween Animation for you!

Before we talk about adding animation to SurfaceView, let’s take a look at how to implement Tween Animation and the four effects in Tween in View;

MyViewAnimation .Java

< p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial; font-size:14px; line-height:26px">

[java] view plain copy

  1. packagecom.himi.frameAnimation;
  2. import android.content.Con text;
  3. importandroid.graphics.Bitmap; span>
  4. importandroid.graphics.BitmapFactory;
  5. importandroid.graphics.Canvas;
  6. import android.graphics.Color; android.graphics.Color;< /span>
  7. import android.graphics.Paint;
  8. import android.view.KeyEvent;
  9. importandroid.view .View;
  10. import android.view.animation.AlphaAnimation;
  11. importandroid.view.animation.Animation;
  12. importandroid.view.animation.RotateAnimation;
  13. import Android.view.animation.ScaleAnimation;
  14. importandroid.view.animation.TranslateAnimation;
  15. /**​< /span>
  16. *@authorHimi
  17. *@AlphaAnimation Gradient Transparency animation effect
  18. *@ScaleAnimation Gradient size scaling animation effect
  19. *@TranslateAnimation Screen transition position moving animation effect
  20. *@RotateAnimation Screen transfer rotation animation effect
  21. */
  22. publicclassMyViewAnimationextends View{ /span>
  23. privatePaint paint;
  24. privateBitmap bmp;
  25. private intx =50; < /li>
  26. private< /span>Animation mAlphaAnimation;
  27. privateAnimationmScaleAnimation;
  28. privateAnimationmTranslateAnimation;
  29. privateAnimationmRotateAnimation;
  30. publicMyViewAnimation(Contextcontext){
  31. < span style="margin:0px; padding:0px; border:none; color:black; background-color:inherit">super(context) ;
  32. paint=newPaint();
  33. paint.setAntiAlias(true);
  34. bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon );
  35. this.setFocusable(true);//OnKeyDown method is called only when the View gets focus span>
  36. @Override
  37. protected void onDraw(Canvas canvas) {    
  38.         super.onDraw(canvas);    
  39.         canvas.drawColor(Color.BLACK);    
  40.         paint.setColor(Color.WHITE);    
  41.         canvas.drawText(“Himi”, x, 50, paint);//备注1    
  42.         canvas.drawText(“方向键↑ 渐变透明度动画效果”80this.getHeight() – 80, paint);    
  43.         canvas.drawText(“方向键↓ 渐变尺寸伸缩动画效果”80this.getHeight() – 60, paint);    
  44.         canvas.drawText(“方向键← 画面转换位置移动动画效果”80this.getHeight() – 40, paint);    
  45.         canvas.drawText(“方向键→ 画面转移旋转动画效果”80this.getHeight() – 20, paint);    
  46.         canvas.drawBitmap(bmp, this.getWidth() / 2 – bmp.getWidth() / 2,     
  47.                 this.getHeight() / 2 – bmp.getHeight() / 2, paint);    
  48.         x += 1;    
  49.     }    
  50.     public boolean onKeyDown(int keyCode, KeyEvent event) {    
  51.         if (keyCode == KeyEve nt.KEYCODE_DPAD_UP) {//渐变透明度动画效果    
  52.             mAlphaAnimation = new AlphaAnimation(0.1f, 1.0f);    
  53.             //第一个参数fromAlpha 为动画开始时候透明度    
  54.             //第二个参数toAlpha 为动画结束时候透明度    
  55.             //注意:取值范围[0-1];[完全透明-完全不透明]    
  56.             mAlphaAnimation.setDuration(3000);    
  57.             ////设置时间持续时间为3000 毫秒=3秒    
  58.             this.startAnimation(mAlphaAnimation);    
  59.         } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {//渐变尺寸伸缩动画效果    
  60.             mScaleAnimation = new ScaleAnimation(0.0f, 1.5f, 0.0f, 1.5f, Animation    
  61.                     .RELATIVE_TO_PARENT, 0.5f, Animation.RELATIVE_TO_PARENT, 0.0f);    
  62.             //第一个参数fromX为动画起始时X坐标上的伸缩尺寸    
  63.             //第二个参数toX为动画结束时X坐标上的伸缩尺寸    
  64.             //第三个参数fromY为动画起始时Y坐标上的伸缩尺寸    
  65.             //第四个参数toY 为动画结束时Y 坐标上的伸缩尺寸    
  66.             //注意:    
  67.             //0.0表示收缩到没有    
  68.             //1.0表示正常无伸缩    

  69.             //值小于1.0表示收缩    
  70.             //值大于1.0表示放大    
  71.             //—–我这里1-4参数表明是起始图像大小不变,动画终止的时候图像被放大1.5倍    
  72.             //第五个参数pivotXType 为动画在X 轴相对于物件位置类型    
  73.             //第六个参数pivotXValue 为动画相对于物件的X 坐标的开始位置    
  74.             //第七个参数pivotXType 为动画在Y 轴相对于物件位置类型    
  75.             //第八个参数pivotYValue 为动画相对于物件的Y 坐标的开始位置    
  76.             //提示:位置类型有三种,每种效果大家自己尝试哈~这里偷下懒~    
  77.             //毕竟亲眼看到效果的区别才记忆深刻~    
  78.             //Animation.ABSOLUTE 、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT    
  79.             mScaleAnimation.setDuration(2000);    
  80.             this.startAnimation(mScaleAnimation);    
  81.         } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {//画面转换位置移动动画效果    
  82.             mTranslateAnimation = new TranslateAnimation(0100 0100);    
  83.             //第一个参数f romXDelta为动画起始时X坐标上的移动位置    
  84.             //第二个参数toXDelta为动画结束时X坐标上的移动位置    
  85.             //第三个参数fromYDelta为动画起始时Y坐标上的移动位置    
  86.             //第四个参数toYDelta 为动画结束时Y 坐标上的移动位置    
  87.             mTranslateAnimation.setDuration(2000);    
  88.             this.startAnimation(mTranslateAnimation);    
  89.         } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {//画面转移旋转动画效果    
  90.             mRotateAnimation = new RotateAnimation(0.0f, 360.0f,     
  91.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);    
  92.             //第一个参数fromDegrees为动画起始时的旋转角度    
  93.             //第二个参数toDegrees 为动画旋转到的角度    
  94.             //第三个参数pivotXType 为动画在X 轴相对于物件位置类型    
  95.             //第四个参数pivotXValue 为动画相对于物件的X 坐标的开始位置    
  96.             //第五个参数pivotXType 为动画在Y 轴相对于物件位置类型    
  97.             //第六个参数pivotYValue 为动画相对于物件的Y 坐标的开始位置    
  98.             mRotateAnimation.setDuration(3000);    
  99.             this.startAnimation(mRotateAnimation);    
  100.         }    
  101.         ret urn super.onKeyDown(keyCode, event);    
  102.     }    
  103. }  


补充:有童鞋说对三种相对位置不太理解,那么我简单说补充下:

//Animation.ABSOLUTE 相对位置是屏幕左上角,绝对位置!/ /Animation.RELATIVE_TO_SELF 相对位置是自身View;取值为0,是自身左上角,取值为1是自身的右下角;//Animation.RELATIVE_TO_PARENT 相对父类View的位置

当设定了位置类型之后,会让你传入X或者Y的值,这里的X,Y可以理解成为一个点坐标!比如是旋转动画,那么这个(X,Y)就是旋转中心点!


OK,对于Tween Animation下的每种动画效果的实例化的每个参数都解释的很详细了!其实动画的实现不光用代码可以实现,在xml中注册实现也是可以的,这里就不多写了,大家可以自己去尝试写一下,那么在view中我们播放一种特效动画,只要实例化其对象,然后设置下参数,然后startAnimation()就好了,步骤很简单,只是每个动画实例化的参数确有着千变万化的改法,这些我也没法子一一来给大家演示,大家可以自己改改参数看看实际的效果!当然对于每种动画我们不光有设置播放的时候,还有一些属性和方法可以调用,比如Animation.restart()重放动画,getTransformation()此方法返回假,说明动画完成等等很多属性,请各位童鞋自定实验 o(∩_∩)o 哈哈~

 

顺便先解释下MyViewAnimation .java 类中onDraw()方法里的(备注1)!其实这里我是想跟大家说明下Android Animation实现机制

                                                 【启动任意一种动画效果之前 和 之后 的对比图】

 

            

 

很明显、”Himi”字样在动画开始前和开始后出现了移动,而且在MyViewAnimation.java中我没有使用Runnable接口,也没有调用刷新的函数,那么我来给各位童鞋解释下原因:

 

  动画的每种变换其实内部都是一次矩阵运算。在Android 中,Canvas 类中包含当前矩阵,当调用 Canvas.drawBitmap (bmp, x, y, Paint) 绘制时,android 会先把 bmp 做一次矩阵运算,然后将运算的结果显示在 Canvas 上,然后不断修改 Canvas 的矩阵并刷新屏幕,View 里的对象就会不停的做图形变换,动画就形成了。

 

还有一点提醒大家:动画的播放是对整个游戏画布进行的操作,这一点要知道哟~

 

那么下面就要给大家介绍如何在我们的SurfaceView中运用Tween Animation!


 

MySurfaceViewAnimation.java 

[java] view plain copy

  1. package com.himi.frameAnimation;  
  2. import android.content.Context;  
  3. import android.graphics.Bitmap;  
  4. import android.graphics.BitmapFactory;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;   
  7. import android.graphics.Paint;   
  8. import android.util.Log;  
  9. import android.view.KeyEvent;  
  10. import android.view.SurfaceHolder;  
  11. import android.view.SurfaceView;  
  12. import android.view.SurfaceHolder.Callback;  
  13. import android.view.animation.AlphaAnimation;  
  14. import android.view.animation.Animation;  
  15. import android.view.animation.RotateAnimation;  
  16. import android.view.animation.ScaleAnimation;   
  17. import android.view.animation.TranslateAnimation;  
  18. /** 
  19.  *@author Himi 
  20.  */  
  21. public class MySurfaceViewAnimation extends SurfaceView implements Callback, Runnable {  
  22.     private Thread th = new Thread(this);  
  23.     private SurfaceHolder sfh;  
  24.     private Canvas canvas;  
  25.     private Paint paint;  
  26.     private Bitmap bmp;  
  27.     ///   
  28. private Animation mAlphaAnimation;  
  29. private Animation mScaleAnimation;  
  30. private Animation mTranslateAnimation;  
  31. private Animation mRotateAnimation;  
  32. public MySurfaceViewAnimation(Context context) {  
  33.     super(context);  
  34.     Log.v(“Himi”“MySurfaceView”);  
  35.     this.setKeepScreenOn(true);  
  36.     bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);  
  37.     sfh = this.getHolder();  
  38.     sfh.addCallback(this);  
  39.     paint = new Paint();  
  40.     paint.setAntiAlias(true);  
  41.     setFocusable(true);  
  42.     setFocusableInTouchMode(true);  
  43. //  this.setBackgroundResource(R.drawable.icon);//备注2  
  44. }  
  45. public void surfaceCreated(SurfaceHolder holder) {  
  46.     Log.v(“Himi”“surfaceCreated”);  
  47.     th.start();  
  48. }  
  49. public void draw() {  
  50.     try {  
  51.         canvas = sfh.lockCanvas();  
  52.         if (canvas != null) {  
  53.             canvas.drawColor(Color.BLACK);  
  54.             paint.setColor(Color.WHITE);  
  55.             canvas.drawText(“方向键↑ 渐变透明度动画效果”80this.getHeight() – 80, paint);  
  56.             canvas.drawText(“方向键↓ 渐变尺寸伸缩动画效果”80this.getHeight() – 60, paint);  
  57.             canvas. drawText(“方向键← 画面转换位置移动动画效果”80this.getHeight() – 40, paint);  
  58.             canvas.drawText(“方向键→ 画面转移旋转动画效果”80this.getHeight() – 20, paint);  
  59.             canvas.drawBitmap(bmp, this.getWidth() / 2 – bmp.ge tWidth() / 2,   
  60.                     this.getHeight() / 2 – bmp.getHeight() / 2, paint);  
  61.         }  
  62.     } catch (Exception e) {  
  63.         Log.v(“Himi”“draw is Error!”);  
  64.     } finally {  
  65.         sfh.unlockCanvasAndPost(canvas);  
  66.     }  
  67. }  
  68. @Override  
  69. public boolean onKeyDown(int keyCode, KeyEvent event) {  
  70.     if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {//渐变透明度动画效果  
  71.         mAlphaAnimation = new AlphaAnimation(0.1f, 1.0f);  
  72.         mAlphaAnimation.setDuration(3000);  
  73.         this.startAnimation(mAlphaAnimation);  
  74.     } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {//渐变尺寸伸缩动画效果  
  75.         mScaleAnimation = new ScaleAnimation(0.0f, 2.0f,   
  76.                 1.5f, 1.5f, Animation.RELATIVE_TO_PARENT,   
  77.                 0.5f, Animation.RELATIVE_TO_PARENT, 0.0f);  
  78.         mScaleAnimation.setDuration(2000);  
  79.         this.startAnimation(mScaleAnimation);  
  80.     } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {//画面转换位置移动动画效果  
  81.         mTranslateAnimation = new TranslateAnimation(01000100);  
  82.         mTranslateAnimation.setDuration(2000);  
  83.         this.startAnimation(mTranslateAnimation);  
  84.     } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {//画面转移旋转动画效果  
  85.         mRotateAnimation = new RotateAnimation(0.0f, 360.0f,   
  86.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);  
  87.         mRotateAnimation.setDuration(3000);  
  88.         this.startAnimation(mRotateAnimation);  
  89.     }  
  90.     return super.onKeyDown(keyCode, event);  

  91. }  
  92. public void run() {  
  93.     // TODO Auto-generated method stub  
  94.     while (true) {  
  95.         draw();  
  96.         try {  
  97.             Thread.sleep(100);  
  98.         } catch (Exception ex) {  
  99.         }  
  100.     }  
  101. }  
  102. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  103.     Log.v(“Himi”“surfaceChanged”);  
  104. }  
  105. public void surfaceDestroyed(SurfaceHolder holder) {  
  106.     Log.v(“Himi”“surfa ceDestroyed”);  
  107.     }  
  108. }  

 

  动画代码实现跟View中的做法一样,运行模拟器发现按键没效果,不是按键没触发是本来就存在问题, – -。 but!大家可以把此类里有一行,也就是(备注2)的注释打开,我们给设置背景图,然后在模拟器上的运行效果如下图:

 

                                       

 

很明显的看到,我们的动画正常运行了,虽然效果并不是我们想到的!但是这里可以说明一点问题:

                                                SurfaceView 本身具备双缓冲机制!!!!!

      有些文章里说“给SurfaceView添加双缓冲”,其实是在画蛇添足 – -,而且介绍的时候拿着单线程与双线程例子来解释双缓冲更高效的实现方法;我想弱弱的问什么是双缓冲? ? ?如果SurfaceView不具备双缓冲,那敢问上面这张截图如何解释? ? ? ?

      其实要实现双缓冲,只需要是新建一个Bitmap和Canvas,用这个新建的Canvas把正弦波画到新建的Bitmap,画完再通过sfh.lockCanvas获取SurfaceView对应的Canvas,用这个Canvas把新建的Bitmap画到SurfaceView上去,这才叫双缓冲; 还有双缓存和多线程没关系!

 

 那么View中动画的实现机制是在不断的刷屏不断的重复调用重写的onDraw()方法、而在Surfaceview的那张截图确实也正常的动画操作了,原因又何在?而且我们设置的背景图覆盖我们draw出来的字体! !效果很不理想;那么经过考虑我决定利用布局把View和SurfaceView都一并显示,用View主要去完成动画部分,(那么关于如何一并显示,或者说同时在SurfaceView中添加组件,在之前的【Android 2D开发之六】 和 【Android 2D开发之七】都有了详细讲解,那么在这里),当然一并显示也会有问题,比如我们存在了view和Surfaceiew,那么按键的时候触发的哪个?或者说如何去控制这两个View?放心,我下面就跟大家一一来讲解!

   

下面先让我们把我们的view 和 Surfaceview 先同时显示出来:【黑色的是MyView (View),白色是MySurfaceView(SurfaceView)

 

                                                        先上张运行截图:  (图4)


                                

 

main.xml中的代码

[xhtml]  view plain  copy

  1. xml version=“1.0” encoding=“utf-8”?>  
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”  
  3.     android:orientation=“vertical”  
  4.     android:layout_width=“fill_parent”  
  5.     android:layout_height=“fill_parent”  
  6.     >   
  7.     <RelativeLayout  
  8.             android:layout_width=“fill_parent”  
  9.             android:layout_height=“wrap_content”  
  10.             android:layout_weight=“1” >  
  11.        <com.himi.MySurfaceView android:id=“@+id/view3d”  
  12.             android:layout_width=“fill_parent”  
  13.             android:layout_height=“fill_parent”/>     
  14.     <com.himi.MyView android:id=“@+id/myview”  
  15.             android:layout_width=“fill_parent”  
  16.             android:layout_height=“fill_parent”/>     
  17.     RelativeLayout>     
  18. LinearLayout>  

xml中我们注册了我们自定义的view-MyView 和 SurfaceView-MySurfaceView;

需要强调的有两点:

1 : 当我们xml中注册我们的View时,我们View类中的构造函数必须要用

      public MyView(Context context, AttributeSet attrs) {} 两个参数的形式,以前的文章有讲解。

 

2 : 当我们在Xml中注册两个View的时候,它们显示的次序就是根据xml注册的顺序来显示,比如上面我们先注册了MySurfaceView,然后注册的MyView ,那么显示的时候会把后添加进去的MyView显示在最上层!

 

下面我们来看MySurfaceView.java中的代码:

 

[java] view plain copy

    package com.himi;  
  1. import android.content.Context;  
  2. import android.graphics.Canvas;  
  3. import android.graphics.Color;  
  4. import android.graphics.Paint;  
  5. import android.util.AttributeSet;  
  6. import android.view.KeyEvent;   
  7. import android.view.SurfaceHolder;  
  8. import android.view.SurfaceView;   
  9. import android.view.SurfaceHolder.Callback;    
  10. /** 
  11.  *  
  12.  * @author Himi 
  13.  * 
  14.  */  
  15. public class MySurfaceView extends SurfaceView implements Callback, Runnable {  
  16.     public static MySurfaceView msrv ;//—-备注1  
  17.     private int move_x = 2, x = 20;  
  18.     private Thread th;  
  19.     private SurfaceHolder sfh;  
  20.     private Canvas canvas;  
  21.     private Paint p;   
  22.     public MySurfaceView(Context context, AttributeSet attrs) {   
  23.         super(context, attrs);  < /span>
  24.         msrv=this;  
  25.         p = new Paint();   
  26.         p.setAntiAlias(true);  
  27.         sfh = this.getHolder();  
  28.         sfh.addCallback(this);  
  29.         th = new Thread(this);  
  30.         this.setKeepScreenOn(true);   
  31.          this.setFocusable(true);// —-备注2  
  32.     }   
  33.     public void surfaceCreate d(SurfaceHolder holder) {  
  34.         th.start();   
  35.     }   
  36.     public void draw() {  
  37.         canvas = sfh.lockC anvas();  
  38.         if(canvas!=null){  
  39.             canvas.drawColor(Color.WHITE);  
  40.             canvas.drawText(“我是   – Surfaceview”, x + move_x, 280, p);  
  41.             sfh.unlockCanvasAndPost(canvas);  
  42.         }   
  43.     }  
  44.     private void logic() {    
  45.         x += move_x;  
  46.         if (x > 200 || x < 80) {  
  47.             move_x = -move_x;  
  48.         }  
  49.     }  
  50.     @Override  
  51.     public boolean onKeyDown(< /span>int key, KeyEvent event) { //备注2  
  52.         return super.onKeyDown(key, event);  
  53.     }   
  54.        
  55.     public void run() {  
  56.         // TODO Auto-generated method stub  
  57.         while (true) {  
  58.             draw();  
  59.             logic();  
  60.             try {  
  61.                 Thread.sleep(100);  
  62.             } catch (Exception ex) {  
  63.             }  
  64.         }  
  65.     }    
  66.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  67.             int height) {   
  68.     }   
  69.     public void surfaceDestroyed(SurfaceHolder holder) {   
  70.     }  
  71. }  

 

代码都很熟悉了, 主要我们来给大家解释下备注1,备注2:

备注1:

   我在两个MyView 和 MySurfaceView中都定义了本类一个静态对象,然后在初始化的时候都利用=this的形式进行了实例化;

注意:=this; 的这种实例形式要注意!只能在当前程序中仅存在一个本类对象才可使用!

       为什么要实例两个View的实例而且定义成静态,这样做主要为了类之间方便调用和操作!比如在我们这个项目中,我这样做是为了在MainActivity中去管理两个View按键焦点!下面我会给出MainActivity的代码,大家一看便知;

 

备注2:   

 我在两个MyView 和 MySurfaceView中都对获取按键焦点注释掉了,而是在别的类中的调用其View的静态实例对象就可以任意类中对其设置!这样就可以很容易去控制到底谁来响应按键了。

 

这里还要强调一下:当xml中注册多个 View的时候,当我们点击按键之后,Android会先判定哪个View setFocusable(true)设置焦点了,如果都设置了,那么Android 会默认响应在xml中第一个注册的view ,而不是两个都会响应。那么为什么不同时响应呢?我解释下:

上面这截图是Android SDK Api的树状图,很明显SurfaceView继承了View,它俩是基继承关系,那么不管是子类还是基类一旦响应了按键,其基类或者父类就不会再去响应;

 

下面我们来看MainActivity.java:

 

[java] view plain copy

  1. package com.himi;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;   
  4. import android.view.KeyEvent;  
  5. import android.view.Window;  
  6. import android.view.WindowManager;  
  7. /** 
  8.  *  
  9.  * @author Himi 
  10.  * 
  11.  */  
  12. public class MainActivity extends Activity {  
  13.     /** Called when the activity is first created. */   
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         this.requestWindowFeature(Window.FEATURE_NO_TITLE);  
  18.         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  19.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  20.         setContentView(R.layout.main);   
  21.         MySurfaceView.msrv.setFocusable(false);//备注1< span style="margin:0px; padding:0px; border:none; background-color:inherit">  
  22.         MyView.mv.setFocusable(true);//备注1  
  23.     }  
  24.     @Override  
  25.     public boolean onKeyDown(int keyCode, KeyEvent event) {//备注2  
  26.         return super.onKeyDo wn(keyCode, event);  
  27.     }  
  28.       
  29. }  

 

备注1:

   这里是当程序运行的时候我们默认让我们的MyView(View)来响应按键。通过类名调用对应的View实例,然后设置获取焦点的函数;

备注2:

    这里要注意:不管你在xml中注册了多少个View ,也不管View是否都设置了获取焦点,只要你在 MainActivity 中重写onKeyDown()函数,Android 就会调用此函数。

 

那么直接在SurfaceView中进行实现动画的想法这里没有得到很好的解决,而是我利用布局的方式来一同显示的方式,希望各位童鞋如果有好的方法,在SurfaceView中直接能使用动画的建议和想法,希望留言给我,大家一起学习 讨论,谢谢 下面给出项目源码:

 

源码下载地址: http://www.himigame.com/android-game/331.html

[java] view plain copy

  1. packa ge com.himi.frameAnimation;    
  2. import android.content.Context;    
  3. import android.graphics.Bitmap;    
  4. import android.graphics.BitmapFactory;    
  5. import android.graphics.Canvas;    

  6. import android.graphics.Color;    
  7. import android.graphics.Paint;    
  8. import android.view.KeyEvent;    
  9. import android.view.View;    
  10. import android.view.animation.AlphaAnimation;    
  11. import android.view.animation.Animation;    
  12. import android.view.animation.RotateAnimation;    
  13. import android.view.animation.ScaleAnimation;    
  14. import android.view.animation.TranslateAnimation;    
  15. /**  
  16.  *@author Himi  
  17.  *@AlphaAnimation 渐变透明度动画效果  
  18.  *@ScaleAnimation 渐变尺寸伸缩动画效果  
  19.  *@TranslateAnimation 画面转换位置移动动画效果  
  20.  *@RotateAnimation 画面转移旋转动画效果  
  21.  */    
  22. public class MyViewAnimation extends View {    
  23.     private Paint paint;    
  24.     private Bitmap bmp;    
  25.     private int x = 50;    
  26.     private Animation mAlphaAnimation;    
  27.     private Animation mScaleAnimation;    
  28.     private Animation mTranslateAnimation;    < /span>
  29.     private Animation mRotateAnimation;    
  30.     public MyViewAnimation(Context context) {    
  31.         super(context);    
  32.         paint = new Paint();    
  33.         paint.setAntiAlias(t rue);    
  34.         bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);    
  35.         this.setFocusable(true);//只有当该View获得焦点时才会调用onKeyDown方法     
  36.     }    
  37.     @Override    
  38.     protected void onDraw(Canvas canvas) {    
  39.         super.onDraw(canvas);    
  40.         canvas.drawColor(Color.BLACK);    
  41.         paint.setColor(Color.WHITE);    
  42.         canvas.drawText(“Himi”, x, 50, paint);//备注1    
  43.         canvas.drawText(“方向键↑ 渐变透明度动画效果”80this.getHeight() – 80, paint);    
  44.         canvas.drawText(“方向键↓ 渐变尺寸伸缩动画效果”80this.getHeight() – 60, paint);    
  45.         canvas.drawText(“方向键← 画面转换位置移动动画效果”80this.getHeight() – 40, paint);    
  46.         canvas.drawText(“方向键→ 画面转移旋转动画效果”80this.getHeight() – 20, paint);    
  47.         canvas.drawBitmap(bmp, this.getWidth() / 2 – bmp.getWidth() / 2,     
  48.                 this.getHeight() / 2 – bmp.getHeight() / 2, paint);    
  49.         x += 1;    
  50.     }    
  51.     public boolean onKeyDown(int keyCode, KeyEvent event) {    
  52.         if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {//渐变透明度动画效果    
  53.             mAlphaAnimation = new AlphaAnimation(0.1f, 1.0f);    
  54.             //第一个参数fromAlpha 为动画开始时候透明度    
  55.             //第二个参数toAlpha 为动画结束时候透明度    
  56.             //注意:取值范围[0-1];[完全透明-完全不透明]    
  57.             mAlphaAnimation.setDuration(3000);    
  58.             ////设置时间持续时间为3000 毫秒=3秒    
  59.             this.startAnimation(mAlphaAnimation);    
  60.         } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {//渐变尺寸伸缩动画效果    
  61.             mScaleAnimation = new ScaleAnimation(0.0f, 1.5f, 0.0f, 1.5f, Animation    
  62.                     .RELATIVE_TO_PARENT, 0.5f, Animation.RELATIVE_TO_PARENT, 0.0f);    
  63.             //第一个参数fromX为动画起始时X坐标上的伸缩尺寸    
  64.             //第二个参数toX为动画结束时X坐标上的伸缩尺寸    
  65.             //第三个参数fromY为动画起始时Y坐标上的伸缩尺寸    
  66.             //第四个参数toY 为动画结束时Y 坐标上的伸缩尺寸    
  67.             //注意:    
  68.             //0.0表示收缩到没有    
  69.             //1.0表示正常无伸缩    
  70.             //值小于1.0表示收缩    
  71.             //值大于1.0表示放大    
  72.             //—–我这里1-4参数表明是起始图像大小不变,动画终止的时候图像被放大1.5倍    
  73.             //第五个参数pivotXType 为动画在X 轴相对于物件位置类型    
  74.             //第六个参数pivotXValue 为动画相对于物件的X 坐标的开始位置    
  75.             //第七个参数pivotXType 为动画在Y 轴相对于物件位置类型    
  76.             //第八个参数pivotYValue 为动画相对于物件的Y 坐标的开始位置    
  77.             //提示:位置类型有三种,每种效果大家自己尝试哈~这里偷下懒~    
  78.             //毕竟亲眼看到效果的区别才记忆深刻~    
  79.             //Animation.ABSOLUTE 、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT    
  80.             mScaleAnimation.setDuration(2000);    
  81.             this.startAnimation(mScaleAnimation);    
  82.         } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {//画面转换位置移动动画效果    
  83.             mTranslateAnimation = new TranslateAnimation(01000100);    
  84.             //第一个参数fromXDelta为动画起始时X坐标上的移动位置    
  85.             //第二个参数toXDelta为动画结束时X坐标上的移动位置    
  86.             //第三个参数fromYDelta为动画起始时Y坐标上的移动位置    
  87.             //第四个参数toYDelta 为动画结束时Y 坐标上的移动位置    
  88.             mTranslateAnimation.setDuration(2000);    
  89.             this.startAnimation(mTranslateAnimation);    
  90.         } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {//画面转移旋转动画效果    
  91.             mRotateAnimation = new RotateAnimation(0.0f, 360.0f,     
  92. < li style="border-style:none none none solid; border-left-width:3px; border-left-color:rgb(108,226,108); list-style:decimal-leading-zero outside; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important; background-color:rgb(248,248,248)">                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);    

  93.             //第一个参数fromDegrees为动画起始时的旋转角度    
  94.             //第二个参数toDegrees 为动画旋转到的角度    
  95.             //第三个参数pivotXType 为动画在X 轴相对于物件位置类型    
  96.             //第四个参数pivotXValue 为动画相对于物件的X 坐标的开始位置    
  97.             //第五个参数pivotXType 为动画在Y 轴相对于物件位置类型    
  98.             //第六个参数pivotYValue 为动画相对于物件的Y 坐标的开始位置    
  99.             mRotateAnimation.setDuration(3000);    
  100.             this.startAnimation(mRotateAnimation);    
  101.         }    
  102.         return super.onKeyDown(keyCode, event);    
  103.     }    
  104. }  

[java] view plain copy

[java] view plain copy

[java] view plain copy

  1. package com.himi.frameAnimation;  
  2. import android.content.Context;  
  3. import android.graphics.Bitmap;  
  4. import android.graphics.BitmapFactory;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;   
  7. import android.graphics.Paint;   
  8. import android.util.Log;  
  9. import android.view.KeyEvent;  
  10. import android.view.SurfaceHolder;  
  11. import android.view.SurfaceView;  
  12. import android.view.SurfaceHolder.Callback;  
  13. import android.view.animation.Al phaAnimation;  
  14. import android.view.animation.Animation;  
  15. import android.view.animation.RotateAnimation;  
  16. import android.view.animation.ScaleAnimation;   
  17. import android.view.animation.TranslateAnimation;  
  18. /** 
  19.  *@author Himi 
  20.  */< span style="margin:0px; padding:0px; border:none; background-color:inherit">  
  21. public class MySurfaceViewAnimation extends SurfaceView implements Callback, Runnable {  
  22.     private Thread th = new Thread(this);  
  23.     private< /span> SurfaceHolder sfh;  
  24.     private Canvas canvas;  
  25.     private Paint paint;  
  26.     private Bitmap bmp;  
  27.     ///   
  28. private Animation mAlphaAnimation;  
  29. private Animation mScaleAnimation;  
  30. private Animation mTranslateAnimation;  
  31. private Animation mRotateAnimation;  
  32. < li style="border-style:none none none solid; border-left-width:3px; border-left-color:rgb(108,226,108); list-style:decimal-leading-zero outside; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important; background-color:rgb(248,248,248)"> public MySurfaceViewAnimation(Context context) {  

  33.     super(context);  
  34.     Log.v(“Himi”“MySurfaceView”);  
  35.     this.setKeepScreenOn(true);  
  36.     bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);  
  37.     sfh = this.getHolder();  
  38.     sfh.addCallback(this);  
  39.     paint =  new Paint();  
  40.     paint.setAntiAlias(true);  
  41.     setFocusable(true);  
  42.     setFocusableInTouchMode(true);  
  43. //  this.setBackgroundResource(R.drawable.icon);//备注2  
  44. }  
  45. public void surfaceCreated(SurfaceHolder holder) {  
  46.     Log.v(“Himi”“surfaceCreated”);  
  47.     th.start();  
  48. }  
  49. public void draw() {  
  50.     try {  
  51.         canvas = sfh.lockCanvas();  
  52.         if (canvas != null) {  
  53.             canvas.drawColor(Color.BLACK);  
  54.             paint.setColor(Color.WHITE);  
  55.             canvas.drawText(“方向键↑ 渐变透明度动画效果”80this.getHeight() – 80, paint);  
  56.             canvas.drawText(“方向键↓ 渐变尺寸伸缩动画效果”80this.getHeight() – 60, paint);  
  57.             canvas.drawText(“方向键← 画面转换位置移动动画效果” 80this.getHeight() – 40, paint);  
  58.             canvas.drawText(“方向键→ 画面转移旋转动画效果”80this.getHeight() – 20, paint);  
  59.             canvas.drawBitmap(bmp, this.getWidth() / 2 – bmp.getWidth() / 2,   
  60.                     this.getHeight() / 2 – bmp.getHeight() / 2, paint);  
  61.         }  
  62.     } catch (Exception e) {  
  63.         Log.v(“Himi”“draw is Error!”);  
  64.     } finally {  
  65.         sfh.unlockCanvasAndPost(canvas);  
  66.     }  
  67. }  
  68. @Override  
  69. public boolean onKeyDown(int keyCode, KeyEvent event) {  
  70.     if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {//渐变透明度动画效果  
  71.         mAlphaAnimation = new AlphaAnimation(0.1f, 1.0f);  
  72.         mAlphaAnimation.setDuration(3000);  
  73.         this.startAnimation(mAlphaAnimation);  
  74.     } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {//渐变尺寸伸缩动画效果  
  75.         mScaleAnimation = new ScaleAnimation(0.0f, 2.0f,   
  76.                 1.5f, 1.5f, Animation.RELATIVE_TO_PARENT,   
  77.                 0.5f, Animation.RELATIVE_TO_PARENT, 0.0f) ;  
  78.         mScaleAnimation.setDuration(2000);  
  79.         this.startAnimation(mScaleAnimation);  
  80.     } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {//画面转换位置移动动画效果  
  81.         mTranslateAnimation = new TranslateAnimation(01000100);  
  82.         mTranslateAnimation.setDuration(2000);  
  83.         this.startAnimatio n(mTranslateAnimation);  
  84.     } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {//画面转移旋转动画效果  
  85.         mRotateAnimation = new RotateAnimation(0.0f, 360.0f,   
  86.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);  
  87.         mRotateAnimation.setDuration(3000);  
  88.         this.startAnimation(mRotateAnimation);  
  89.     }  
  90.     return super.onKeyDown(keyCode, event);  
  91. }  
  92. public void run() {  
  93.     // TODO Auto-generated method stub  
  94.     while (true) {  
  95.         draw();  
  96.         try {  
  97.             Thread.sleep(100);  
  98.         } catch (Exception ex) {  
  99.         }  
  100.     }  
  101. }  
  102. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  103.     Log.v(“Himi”“surfaceChanged”);  
  104. }  
  105. public void surfaceDestroyed(SurfaceHolder holder) {  
  106.     Log.v(“Himi”“surfaceDestroyed”);  
  107.     }  
  108. }  

[java] view plain copy

[java] view plain copy

[xhtml]  view plain  copy

  1. xml version=“1.0” encoding=“utf-8”?>  
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”  
  3.     android:orientation=“vertical”  
  4.     android:layout_width=“fill_parent”  
  5.     android:layout_height=“fill_parent”  
  6.     >   
  7.     <RelativeLayout  
  8.             android:layout_width=“fill_parent”  
  9.             android:layout_height=“wrap_content”  
  10.             android:layout_weight=“1” >  
  11.        <com.himi.MySurfaceView android:id=“@+id/view3d”  
  12.             android:layout_width=“fill_parent”  
  13.             android:layout_height=“fill_parent”/>     
  14.     <com.himi.MyView android:id=“@+id/myview”  
  15.             android:layout_width=“fill_parent”  
  16.             android:layout_height=“fill_parent”/>     
  17.     RelativeLayout>     
  18. LinearLayout>  

[xhtml]  view plain  copy

[xhtml]  view plain  copy

[java] view plain copy

  1. package com.himi;  
  2. import android.content.Context;  
  3. import android.graphics.Canvas;  
  4. import android.graphics.Color;  
  5. import android.graphics.Paint;  
  6. import android.util.AttributeSet;  
  7. import android.view.KeyEvent;   
  8. import android.view.SurfaceHolder;  
  9. import android.view.SurfaceView;   
  10. import android.view.SurfaceHolde r.Callback;    
  11. /** 
  12.  *  
  13.  * @author Himi 
  14.  * 
  15.  */  
  16. public class MySurfaceView extends SurfaceView implements Callback, Runnable {  
  17.     public static MySurfaceView msrv ;//—-备注1  
  18.     private int move_x = 2, x = 20;  
  19.     private Thread th;  
  20.     private SurfaceHolder sfh;  
  21.     private Canvas canvas;  
  22.     private Paint p;   
  23.     public MySurfaceView(Context context, AttributeSet attrs) {   
  24.         super(context, attrs);  
  25.         msrv=this;  
  26.         p = new Paint();   
  27.         p.setAntiAlias(true);  
  28.         sfh = this.getHolder();  
  29.         sfh.addCallback(this);  
  30.         th = new Thread(this);  
  31.         this.setKeepScreenOn(true);   
  32.          this.setFocusable(true);// —-备注2  
  33.     }   
  34.     public void surfaceCreated(SurfaceHolder holder) {  
  35.         th.start();   
  36.     }   
  37.     public void draw() {  
  38.         canvas = sfh.lockCanvas();  
  39.         if(canvas!=null){  
  40.             canvas.drawColor(Color.WHITE);  
  41.             canvas.drawText(“我是   – Surfaceview”, x + move_x, 280, p);  
  42.             sfh.unlockCanvasAndPost(canvas);  
  43.         }   
  44.     }  
  45.     private void logic() {    
  46.         x += move_x;  
  47.         if (x > 200 || x < 80) {  
  48.             move_x = -move_x;  
  49.         }  
  50.     }  
  51.     @Override  
  52.     public boolean onKeyDown(int key, KeyEvent event) { //备注2  
  53.         return super.onKeyDown(key, event);  
  54.     }   
  55.        
  56.     public void run() {  
  57.         // TODO Auto-generated method stub  
  58.         while (true) {  
  59.             draw();  
  60.             logic();  
  61.             try {  
  62.                 Thread.sleep(100);  
  63.             } catch (Exception ex) {  
  64.             }  
  65.         }  
  66.     }    
  67.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  68.             int height) {   
  69.     }   
  70.     public void surfaceDestroyed(SurfaceHolder holder) {   
  71.     }  
  72. }  

[java] view plain copy

[java] view plain copy

[java] view plain copy

  1. package com.himi;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;   
  4. import android.view.KeyEvent;  
  5. import android.view.Window;  
  6. import android.view.WindowManager;  
  7. /** 
  8.  *  
  9.  * @author Himi 
  10.  * 
  11.  */  
  12. public class MainActivity extends Activity {  
  13.     /** Called when the activity is first created. */   
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         this.requestWindowFeature(Window.FEATURE_NO_TITLE);  
  18.         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  19.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  20.         setContentView(R.layout.main);   
  21.         MySurfaceView.msrv.setFocusable(false);//备注1  
  22.         MyView.mv.setFocusable(true);//备注1  
  23.     }  
  24.     @Override  
  25.     public boolean onKeyDown(int keyCode, KeyEvent event) {//备注2  
  26.         return super.onKeyDown(keyCode, event);  
  27.     }  
  28.       
  29. }  

[java] view plain copy

[java] view plain copy

Leave a Comment

Your email address will not be published.