[关闭]
@linux1s1s 2017-01-22T08:27:22.000000Z 字数 4431 阅读 3060

Android 动画 Frame Animation

AndroidAnimation 2016-06


关于帧动画,先看一下官方的介绍:

Frame动画是一系列图片按照一定的顺序展示的过程,和放电影的机制很相似,我们称为逐帧动画。Frame动画可以被定义在XML文件中,也可以完全编码实现。

实例

先定义 @drawable/app_progress_logo

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:oneshot="false"
  4. android:variablePadding="true" >
  5. <item
  6. android:drawable="@drawable/app_progress_logo1"
  7. android:duration="30"/>
  8. <item
  9. android:drawable="@drawable/app_progress_logo2"
  10. android:duration="30"/>
  11. <item
  12. android:drawable="@drawable/app_progress_logo3"
  13. android:duration="30"/>
  14. <item
  15. android:drawable="@drawable/app_progress_logo4"
  16. android:duration="30"/>
  17. <item
  18. android:drawable="@drawable/app_progress_logo5"
  19. android:duration="30"/>
  20. <item
  21. android:drawable="@drawable/app_progress_logo6"
  22. android:duration="30"/>
  23. <item
  24. android:drawable="@drawable/app_progress_logo7"
  25. android:duration="30"/>
  26. <item
  27. android:drawable="@drawable/app_progress_logo8"
  28. android:duration="30"/>
  29. <item
  30. android:drawable="@drawable/app_progress_logo9"
  31. android:duration="30"/>
  32. <item
  33. android:drawable="@drawable/app_progress_logo10"
  34. android:duration="30"/>
  35. <item
  36. android:drawable="@drawable/app_progress_logo11"
  37. android:duration="30"/>
  38. <item
  39. android:drawable="@drawable/app_progress_logo12"
  40. android:duration="30"/>
  41. <item
  42. android:drawable="@drawable/app_progress_logo13"
  43. android:duration="30"/>
  44. <item
  45. android:drawable="@drawable/app_progress_logo14"
  46. android:duration="30"/>
  47. <item
  48. android:drawable="@drawable/app_progress_logo15"
  49. android:duration="30"/>
  50. <item
  51. android:drawable="@drawable/app_progress_logo16"
  52. android:duration="30"/>
  53. <item
  54. android:drawable="@drawable/app_progress_logo17"
  55. android:duration="30"/>
  56. <item
  57. android:drawable="@drawable/app_progress_logo18"
  58. android:duration="30"/>
  59. <item
  60. android:drawable="@drawable/app_progress_logo19"
  61. android:duration="30"/>
  62. </animation-list>

必须以<animation-list>为根元素,以<item>表示要轮换显示的图片,duration属性表示各项显示的时间。XML文件要放在/res/drawable/目录下。

然后 看看UI界面定义

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="@drawable/app_background">
  6. <ImageView
  7. android:id="@+id/splash_logo"
  8. android:layout_width="@dimen/splash_logo_width"
  9. android:layout_height="@dimen/splash_logo_height"
  10. android:layout_centerInParent="true"
  11. android:contentDescription="@null"
  12. android:scaleType="fitXY"
  13. android:src="@drawable/app_progress_logo" />
  14. </RelativeLayout>

接着看看如何使用这个帧动画

  1. public class SplashActivity extends SplashActivity_Base
  2. {
  3. private ImageView mLogo;
  4. @Override
  5. protected void onCreate(Bundle savedInstanceState)
  6. {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_splash);
  9. mLogo = (ImageView) findViewById(R.id.splash_logo);
  10. mLogo.post(new Runnable()
  11. {
  12. @Override
  13. public void run()
  14. {
  15. Drawable progressDrawable = mLogo.getDrawable();
  16. if (progressDrawable instanceof AnimationDrawable)
  17. {
  18. ((AnimationDrawable) progressDrawable).start();
  19. }
  20. }
  21. });
  22. }
  23. ...
  24. }

假如上面的代码在onCreate()方法中这么写会如何?

  1. public class SplashActivity extends SplashActivity_Base
  2. {
  3. private ImageView mLogo;
  4. @Override
  5. protected void onCreate(Bundle savedInstanceState)
  6. {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_splash);
  9. mLogo = (ImageView) findViewById(R.id.splash_logo);
  10. Drawable progressDrawable = mLogo.getDrawable();
  11. if (progressDrawable instanceof AnimationDrawable)
  12. {
  13. ((AnimationDrawable) progressDrawable).start();
  14. }
  15. }
  16. ...
  17. }

运行以后,停留在第一帧 不动了,出现这种现象是因为当我们在onCreate中调用AnimationDrawable的start方法时,窗口Window对象还没有完全初始化,AnimationDrawable不能完全追加到窗口Window对象中,那么该怎么办呢?我们需要把这段代码放在onWindowFocusChanged方法中,当Activity展示给用户时,onWindowFocusChanged方法就会被调用,像下面这样。

  1. @Override
  2. public void onWindowFocusChanged(boolean hasFocus) {
  3. super.onWindowFocusChanged(hasFocus);
  4. Drawable progressDrawable = mLogo.getDrawable();
  5. if (progressDrawable instanceof AnimationDrawable)
  6. {
  7. ((AnimationDrawable) progressDrawable).start();
  8. }
  9. }

当然了,也可以使用View.post(Runnable runnable),当View完全准备好了以后,再启动动画亦可。当然 如果你不想这样通过XML来定义,完全可以通过代码来定义,比如:

  1. AnimationDrawable anim = new AnimationDrawable();
  2. for (int i = 1; i <= 19; i++) {
  3. int id = getResources().getIdentifier("app_progress_logo" + i, "drawable", getPackageName());
  4. Drawable drawable = getResources().getDrawable(id);
  5. anim.addFrame(drawable, 300);
  6. }
  7. anim.setOneShot(false);
  8. image.setBackgroundDrawable(anim);
  9. anim.start();

在实践中遇到的问题小结:

  1. 要在代码中调用Imageview的setBackgroundResource方法,如果直接在XML布局文件中设置其src属性当触发动画时会FC。(这里没有重现)
  2. 在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次。
  3. 最后一点是SDK中提到的,不要在onCreate中调用start,因为AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start(),或者使用View.post(Runnable runnable);
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注