Android 逐帧动画&补间动画

怼烎@ 2022-08-18 10:56 397阅读 0赞

在Android开发中,有的时候为了展示更好的UI效果,通常会通过给一些UI添加动画来达到这一目的,所以Android Api定义了两种动画的Api供开发者使用:逐帧动画和补间动画。

逐帧动画

逐帧动画的原理非常简单,就是通过将一组图片按照一定的次序在一定的时间里顺序播放而达到动画效果的一种动画。在Android中想要使用逐帧动画主要通过

AnimationDrawable这个类来完成的。

1. 创建xml动画

通过xml文件创建动画需要动画xml文件放在res/anim目录下,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
  3. <!-- android:oneshot="false" 设置动画是否重复播放 true:不重复 false 重复 -->
  4. <item android:drawable="@drawable/anim1" android:duration="200"></item>
  5. <item android:drawable="@drawable/anim2" android:duration="200"></item>
  6. <item android:drawable="@drawable/anim3" android:duration="200"></item>
  7. <item android:drawable="@drawable/anim4" android:duration="200"></item>
  8. <item android:drawable="@drawable/anim5" android:duration="200"></item>
  9. <item android:drawable="@drawable/anim6" android:duration="200"></item>
  10. <item android:drawable="@drawable/anim7" android:duration="200"></item>
  11. <item android:drawable="@drawable/anim8" android:duration="200"></item>
  12. <item android:drawable="@drawable/anim9" android:duration="200"></item>
  13. <item android:drawable="@drawable/anim10" android:duration="200"></item>
  14. <item android:drawable="@drawable/anim11" android:duration="200"></item>
  15. </animation-list>

2. 设置动画

在布局文件中设置动画,代码如下:

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical"
  6. tools:context="com.zk.animdemo.MainActivity" >
  7. <Button
  8. android:id="@+id/btn_start"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:text="开启动画" />
  12. <Button
  13. android:id="@+id/btn_stop"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:text="停止动画" />
  17. <!-- 通过xml设置动画 -->
  18. <ImageView
  19. android:id="@+id/iv_anim_show"
  20. android:layout_width="200dp"
  21. android:layout_height="200dp"
  22. android:background="@anim/frame_anim" />
  23. <!-- 通过代码设置逐帧动画 -->
  24. <ImageView
  25. android:id="@+id/iv_anim_show1"
  26. android:layout_width="300dp"
  27. android:layout_height="300dp"/>
  28. </LinearLayout>

3. 获得AnimationDrawable播放动画

在xml文件中给ImageView设置逐帧动画后,动画是不会播放的,必须通过获得AnimationDrawable对象来控制动画的播放和停止效果,所以该类提供了两个方法,播放动画和停止动画:

start():开始播放动画

stop():停止播放动画

代码如下:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. setContentView(R.layout.activity_frame);
  5. mBtnStart = (Button) findViewById(R.id.btn_start);
  6. mBtnStop = (Button) findViewById(R.id.btn_stop);
  7. mIvShow = (ImageView) findViewById(R.id.iv_anim_show);
  8. mIvShow1 = (ImageView) findViewById(R.id.iv_anim_show1);
  9. mBtnStart.setOnClickListener(this);
  10. mBtnStop.setOnClickListener(this);
  11. // 获取帧动画
  12. <span style="white-space:pre"> </span>mAnimation = (AnimationDrawable) mIvShow.getBackground();
  13. //通过代码设置动画
  14. addFrameAnim();
  15. }
  16. @Override
  17. public void onClick(View v) {
  18. switch (v.getId()) {
  19. case R.id.btn_start:
  20. mAnimation.start();
  21. mAnimation1.start();
  22. break;
  23. case R.id.btn_stop:
  24. mAnimation.stop();
  25. mAnimation1.stop();
  26. break;
  27. default:
  28. break;
  29. }
  30. }

4. 通过代码创建动画

当然,Android Api不但提供了通过xml文件的方式创建动画,同时开发者可以通过自己创建一个AnimationDrawable对象来创建动画。代码如下:

  1. /**
  2. * 动过代码设置动画
  3. */
  4. private void addFrameAnim() {
  5. // 通过代码创建帧动画
  6. mAnimation1 = new AnimationDrawable();
  7. // 添加每一帧动画并指定时间
  8. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim1), 200);
  9. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim2), 200);
  10. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim3), 200);
  11. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim4), 200);
  12. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim5), 200);
  13. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim6), 200);
  14. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim7), 200);
  15. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim8), 200);
  16. mAnimation1.addFrame(getResources().getDrawable(R.drawable.anim9), 200);
  17. mAnimation1
  18. .addFrame(getResources().getDrawable(R.drawable.anim10), 200);
  19. mAnimation1
  20. .addFrame(getResources().getDrawable(R.drawable.anim11), 200);
  21. // 设置动画是否重复
  22. mAnimation1.setOneShot(false);
  23. mIvShow1.setBackgroundDrawable(mAnimation1);
  24. }

这样,整个Android逐帧动画的实现就完成了。

效果如下:

SouthEast

补间动画

在补间动画中,开发者不需要向创建逐帧动画那样一一指定每一帧动画的实现效果,只需要指定动画的开始帧和结束帧的效果即可,其他的中间过程都是通过系统自身通过一定的算法计算获得。

Android Api中给我定义了五种补间动画效果:

  • AlphaAnimation:渐变动画
  • ScaleAnimation:缩放动画
  • TranslateAnimation:平移动画
  • RotateAnimation:旋转动画
  • AnimationSet:组合动画

代码如下:

  1. package com.zk.animdemo;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.view.View.OnClickListener;
  6. import android.view.animation.AlphaAnimation;
  7. import android.view.animation.Animation;
  8. import android.view.animation.AnimationSet;
  9. import android.view.animation.AnimationUtils;
  10. import android.view.animation.RotateAnimation;
  11. import android.view.animation.ScaleAnimation;
  12. import android.view.animation.TranslateAnimation;
  13. import android.widget.Button;
  14. import android.widget.ImageView;
  15. public class TweenActivity extends Activity implements OnClickListener {
  16. private Button mBtnAlpha;
  17. private Button mBtnScale;
  18. private Button mBtnTrans;
  19. private Button mBtnRotate;
  20. private Button mBtnSet;
  21. private ImageView mIvShow;
  22. private Animation mAnimation;
  23. private AnimationSet mAnimationSet;
  24. @Override
  25. protected void onCreate(Bundle savedInstanceState) {
  26. super.onCreate(savedInstanceState);
  27. setContentView(R.layout.activity_tween);
  28. mBtnAlpha = (Button) findViewById(R.id.btn_alpha);
  29. mBtnScale = (Button) findViewById(R.id.btn_scale);
  30. mBtnTrans = (Button) findViewById(R.id.btn_translate);
  31. mBtnRotate = (Button) findViewById(R.id.btn_Rotate);
  32. mBtnSet = (Button) findViewById(R.id.btn_set);
  33. mIvShow = (ImageView) findViewById(R.id.iv_show);
  34. mBtnAlpha.setOnClickListener(this);
  35. mBtnScale.setOnClickListener(this);
  36. mBtnTrans.setOnClickListener(this);
  37. mBtnRotate.setOnClickListener(this);
  38. mBtnSet.setOnClickListener(this);
  39. }
  40. @Override
  41. public void onClick(View v) {
  42. switch (v.getId()) {
  43. case R.id.btn_alpha:
  44. // fromAlpha :开始透明度
  45. // toAlpha:结束透明度
  46. mAnimation = new AlphaAnimation(0.1f, 0.9f);
  47. startAnimation();
  48. break;
  49. case R.id.btn_scale:
  50. // fromXScale:x轴开始缩放比例
  51. // toXScale:x轴结束缩放比例
  52. // fromYScale:y轴开始缩放比例
  53. // toYScale: y轴结束缩放比例
  54. // pivotx、pivoty指定中心坐标位置
  55. mAnimation = new ScaleAnimation(0.5f, 2.0f, 0.5f, 2.0f);
  56. // 指定缩放中心位置
  57. mAnimation = new ScaleAnimation(0.5f, 2.0f, 0.5f, 2.0f,
  58. Animation.RELATIVE_TO_SELF, 0.5f,
  59. Animation.RELATIVE_TO_SELF, 0.5f);
  60. startAnimation();
  61. break;
  62. case R.id.btn_translate:
  63. // fromXDelta:起始位置的横坐标
  64. // toXDelta :起结束位置的横坐标
  65. // fromYDelta:起始位置的纵坐标
  66. // toYDelta :结束位置的纵坐标
  67. mAnimation = new TranslateAnimation(-300f, 500f, -300f, 500f);
  68. startAnimation();
  69. break;
  70. case R.id.btn_Rotate:
  71. // fromDegrees: 旋转的起始角度
  72. // toDegrees: 旋转的结束角度
  73. mAnimation = new RotateAnimation(0f, 360f,
  74. Animation.RELATIVE_TO_SELF, 0.5f,
  75. Animation.RELATIVE_TO_SELF, 0.5f);
  76. startAnimation();
  77. break;
  78. case R.id.btn_set:
  79. playAnimSet();
  80. break;
  81. default:
  82. break;
  83. }
  84. }
  85. /**
  86. * 开始动画
  87. */
  88. private void startAnimation() {
  89. // 动画时间
  90. mAnimation.setDuration(3000);
  91. // 动画重复次数
  92. mAnimation.setRepeatCount(10);
  93. // 动画重复模式 重新开始: Animation.RESTART 倒序:Animation.REVERSE
  94. mAnimation.setRepeatMode(Animation.RESTART);
  95. // // 动画执行后保持最后状态
  96. // mAnimation.setFillAfter(true);
  97. // // 设置动画执行后不回到原来状态
  98. // mAnimation.setFillBefore(true);
  99. // // 等待1秒后执行动画
  100. // mAnimation.setStartOffset(1000);
  101. // 通过设置该方法控制动画的变化速度
  102. // mAnimation.setInterpolator();
  103. // 设置Interpolator
  104. // mAnimation.setInterpolator(new AccelerateInterpolator());
  105. mIvShow.startAnimation(mAnimation);
  106. }
  107. /**
  108. * 播放组合动画
  109. */
  110. private void playAnimSet() {
  111. // 创建组合东海
  112. mAnimationSet = new AnimationSet(true);
  113. Animation anim1 = new ScaleAnimation(0.5f, 2.0f, 0.5f, 2.0f);
  114. Animation anim2 = new AlphaAnimation(0.1f, 0.9f);
  115. // 动画时间
  116. anim1.setDuration(3000);
  117. anim2.setDuration(3000);
  118. // 添加动画
  119. mAnimationSet.addAnimation(anim1);
  120. mAnimationSet.addAnimation(anim2);
  121. mAnimationSet.start();
  122. // 播放动画
  123. mIvShow.startAnimation(mAnimationSet);
  124. }
  125. }

当然,和逐帧动画一样,补间动画同样可以通过xml文件创建:

渐变动画:

  1. <alpha xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:duration="3000"
  3. android:fromAlpha="0.1"
  4. android:repeatCount="10"
  5. android:repeatMode="reverse"
  6. android:toAlpha="0.5" />

缩放动画:

  1. <scale xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:duration="3000"
  3. android:fromXScale="0.5"
  4. android:fromYScale="0.5"
  5. android:interpolator="@android:anim/accelerate_interpolator"
  6. android:pivotX="50%"
  7. android:pivotY="50%"
  8. android:toXScale="1.5"
  9. android:toYScale="1.5" />

平移动画:

  1. <translate xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:duration="3000"
  3. android:fromXDelta="0"
  4. android:fromYDelta="0"
  5. android:toXDelta="800"
  6. android:toYDelta="800" />

旋转动画:

  1. <rotate xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:duration="3000"
  3. android:fromDegrees="0"
  4. android:toDegrees="360"
  5. android:repeatCount="10"
  6. android:repeatMode="reverse"/>

组合动画:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <set xmlns:android="http://schemas.android.com/apk/res/android" >
  3. <alpha
  4. android:duration="3000"
  5. android:fromAlpha="0.1"
  6. android:repeatCount="10"
  7. android:repeatMode="reverse"
  8. android:toAlpha="0.5" />
  9. <scale
  10. android:duration="3000"
  11. android:fromXScale="0.5"
  12. android:fromYScale="0.5"
  13. android:interpolator="@android:anim/accelerate_interpolator"
  14. android:pivotX="50%"
  15. android:pivotY="50%"
  16. android:toXScale="1.5"
  17. android:toYScale="1.5" />
  18. </set>

在代码中获得xml动画:

  1. /**
  2. * 加载xml动画
  3. */
  4. private void loadAnimation() {
  5. mAnimation = AnimationUtils.loadAnimation(this, R.anim.alpha_anim);
  6. mAnimationSet = (AnimationSet) AnimationUtils.loadAnimation(this,
  7. R.anim.set_anim);
  8. }

具体效果:

SouthEast 1

Interpolator

在补间动画的代码中相比大家看到了这样的一句代码: mAnimation.setInterpolator(new AccelerateInterpolator());

这里将介绍Android动画中一个非常重要的属性 Interpolator: 主要用于改变动画的变化速率及动画效果。

Android Api提供了几种默认的Interpolator:

SouthEast 2

  • AccelerateDecelerateInterpolator:动画在开始、结束的时候速度慢,在中间速度快。
  • AccelerateInterpolator:动画开始速度慢,结束时速度加快。
  • AnticipateInterpolator:动画开始的时候向后,然后向前。
  • AnticipateOvershootInterpolator:动画开始的时候向后,然后向前甩一定值后,返回最后的值。
  • BounceInterpolator :动画结束的时候弹起。
  • CycleInterpolator:动画循环播放特定的次数,速率改变沿着正弦曲线。
  • DecelerateInterpolator:在动画开始的地方快然后慢。
  • LinearInterpolator:动画匀速变化。
  • OvershootInterpolator:动画向前甩一定值后再回到原来位置。

大家自己可以通过设置interpolator来查看不同的动画效果。

这样关于逐帧动画和补间动画的介绍就到这里了。

发表评论

表情:
评论列表 (有 0 条评论,397人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Android 动画&动画

    在Android开发中,有的时候为了展示更好的UI效果,通常会通过给一些UI添加动画来达到这一目的,所以Android Api定义了两种动画的Api供开发者使用:逐帧动画和补间

    相关 Android动画

    补间动画的优点是可以节省空间。补间动画与逐帧动画在本质上是不同的,逐帧动画通过连续播放图片来模拟动画的效果,而补间动画则是通过在两个关键帧之间补充渐变的动画效果来实现的。目前A