一、帧动画 (Frame Animation)
概念
帧动画是最简单的动画形式,通过连续播放一系列预先定义的静态图片来形成动画效果,类似于传统动画片的制作原理。
特点
-
实现简单
-
资源占用大(需要准备多张图片)
-
不适用于复杂动画场景
实现步骤
1. 准备图片资源
在res/drawable目录下放置帧动画所需的图片序列(如frame1.png, frame2.png...)
2. 创建动画资源文件
在res/drawable目录下创建XML文件定义动画序列:
<!-- res/drawable/frame_animation.xml -->
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false"> <!-- oneshot为false表示循环播放 -->
<item
android:drawable="@drawable/frame1"
android:duration="100"/> <!-- 每帧显示100毫秒 -->
<item
android:drawable="@drawable/frame2"
android:duration="100"/>
<!-- 添加更多帧... -->
</animation-list>
3. 在代码中启动动画
// 在Activity中
ImageView animationView = findViewById(R.id.animation_view);
animationView.setBackgroundResource(R.drawable.frame_animation);
// 获取动画对象并启动
AnimationDrawable frameAnimation = (AnimationDrawable) animationView.getBackground();
frameAnimation.start();
// 停止动画
// frameAnimation.stop();
二、补间动画 (Tween Animation)
概念
补间动画通过对View对象进行一系列简单的变换(平移、缩放、旋转、透明度)来实现动画效果。
特点
-
只能作用于View对象
-
只改变View的绘制位置,不改变View的实际属性
-
资源占用小
四种基本类型
-
平移 (Translate)
-
缩放 (Scale)
-
旋转 (Rotate)
-
透明度 (Alpha)
实现方式
1. XML方式定义动画
<!-- res/anim/alpha_anim.xml 透明度动画 -->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="1.0"
android:toAlpha="0.1" />
<!-- res/anim/translate_anim.xml 平移动画 -->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="100%" />
<!-- res/anim/rotate_anim.xml 旋转动画 -->
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<!-- res/anim/scale_anim.xml 缩放动画 -->
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="2.0"
android:toYScale="2.0" />
2. 代码中加载和使用动画
// 加载动画
Animation alphaAnim = AnimationUtils.loadAnimation(this, R.anim.alpha_anim);
Animation translateAnim = AnimationUtils.loadAnimation(this, R.anim.translate_anim);
Animation rotateAnim = AnimationUtils.loadAnimation(this, R.anim.rotate_anim);
Animation scaleAnim = AnimationUtils.loadAnimation(this, R.anim.scale_anim);
// 启动动画
View view = findViewById(R.id.target_view);
view.startAnimation(alphaAnim);
// 组合动画
AnimationSet animSet = new AnimationSet(true);
animSet.addAnimation(alphaAnim);
animSet.addAnimation(rotateAnim);
view.startAnimation(animSet);
3. 代码动态创建动画
// 透明度动画
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.1f);
alphaAnimation.setDuration(1000);
// 平移动画
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, 1f,
Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, 1f);
translateAnimation.setDuration(1000);
// 旋转动画
RotateAnimation rotateAnimation = new RotateAnimation(
0, 360,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(1000);
// 缩放动画
ScaleAnimation scaleAnimation = new ScaleAnimation(
1.0f, 2.0f, // X轴缩放
1.0f, 2.0f, // Y轴缩放
Animation.RELATIVE_TO_SELF, 0.5f, // 缩放中心X
Animation.RELATIVE_TO_SELF, 0.5f); // 缩放中心Y
scaleAnimation.setDuration(1000);
三、属性动画 (Property Animation)
概念
属性动画是Android 3.0引入的更强大的动画系统,可以实际改变对象的属性值,而不仅仅是View的绘制效果。
特点
-
可以作用于任何对象的属性,不限于View
-
实际改变对象属性值
-
更灵活,功能更强大
-
支持自定义估值器和插值器
核心类
-
ValueAnimator - 值动画,通过平滑过渡值的变化来驱动动画
-
ObjectAnimator - 对象动画,直接对对象的属性进行动画操作
-
AnimatorSet - 动画集合,用于组合多个动画
实现方式
1. 使用ValueAnimator
// 创建从0到1的动画,持续1秒
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.setDuration(1000);
// 添加更新监听
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
// 使用value更新View属性
view.setAlpha(value);
view.setScaleX(value);
view.setScaleY(value);
}
});
// 启动动画
animator.start();
2. 使用ObjectAnimator
// 透明度动画
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
alphaAnim.setDuration(1000);
// 旋转动画
ObjectAnimator rotationAnim = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);
rotationAnim.setDuration(1000);
// 平移动画(X轴)
ObjectAnimator translationXAnim = ObjectAnimator.ofFloat(view, "translationX", 0f, 300f);
translationXAnim.setDuration(1000);
// 缩放动画
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(view, "scaleX", 1f, 2f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(view, "scaleY", 1f, 2f);
// 启动单个动画
alphaAnim.start();
// 使用AnimatorSet组合动画
AnimatorSet set = new AnimatorSet();
set.playTogether(alphaAnim, rotationAnim, translationXAnim); // 同时执行
// 或者按顺序执行
// set.playSequentially(alphaAnim, rotationAnim, translationXAnim);
set.setDuration(1000);
set.start();
3. XML方式定义属性动画
<!-- res/animator/property_animator.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together"> <!-- together表示同时执行,sequentially表示顺序执行 -->
<objectAnimator
android:propertyName="alpha"
android:duration="1000"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:repeatCount="1"
android:repeatMode="reverse"/>
<objectAnimator
android:propertyName="translationX"
android:duration="1000"
android:valueFrom="0"
android:valueTo="300"
android:valueType="floatType"/>
</set>
4. 自定义属性动画
// 自定义View属性
public class CustomView extends View {
private float progress;
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
invalidate(); // 重绘View
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 根据progress值绘制内容
}
}
// 使用ObjectAnimator动画自定义属性
CustomView customView = findViewById(R.id.custom_view);
ObjectAnimator progressAnim = ObjectAnimator.ofFloat(customView, "progress", 0f, 100f);
progressAnim.setDuration(2000);
progressAnim.start();
5. 使用插值器和估值器
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", 0f, 300f);
anim.setDuration(1000);
// 设置插值器(控制动画变化速率)
anim.setInterpolator(new AccelerateDecelerateInterpolator()); // 先加速后减速
// anim.setInterpolator(new LinearInterpolator()); // 线性
// anim.setInterpolator(new AccelerateInterpolator()); // 加速
// anim.setInterpolator(new DecelerateInterpolator()); // 减速
// anim.setInterpolator(new AnticipateOvershootInterpolator()); // 回弹效果
// 自定义插值器
anim.setInterpolator(new TimeInterpolator() {
@Override
public float getInterpolation(float input) {
// 自定义插值逻辑
return input * input; // 二次方曲线
}
});
// 设置估值器(控制如何计算属性值)
anim.setEvaluator(new TypeEvaluator<Float>() {
@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {
// 自定义估值逻辑
return startValue + fraction * (endValue - startValue);
}
});
anim.start();
四、三种动画对比
特性 | 帧动画 | 补间动画 | 属性动画 |
---|---|---|---|
实现方式 | 多张图片连续播放 | 对View进行图形变换 | 改变对象属性值 |
作用对象 | ImageView | View | 任意对象 |
是否改变实际属性 | 否 | 否 | 是 |
灵活性 | 低 | 中 | 高 |
性能消耗 | 高 | 低 | 中 |
适用场景 | 简单序列动画 | View的简单动画 | 复杂动画、自定义属性动画 |
五、建议
-
简单UI动画:优先考虑补间动画,实现简单且性能较好
-
复杂动画或需要交互:使用属性动画,功能更强大
-
小型的连续图片动画:可以使用帧动画
-
内存优化:帧动画要注意图片大小和数量,避免OOM
-
动画性能:避免在动画过程中执行耗时操作
-
动画复用:尽量使用XML定义动画,便于复用和维护
-
新项目:建议主要使用属性动画,功能最全面