【安卓开发】帧动画、补间动画、属性动画

一、帧动画 (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的实际属性

  • 资源占用小

四种基本类型

  1. 平移 (Translate)

  2. 缩放 (Scale)

  3. 旋转 (Rotate)

  4. 透明度 (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

  • 实际改变对象属性值

  • 更灵活,功能更强大

  • 支持自定义估值器和插值器

核心类

  1. ValueAnimator - 值动画,通过平滑过渡值的变化来驱动动画

  2. ObjectAnimator - 对象动画,直接对对象的属性进行动画操作

  3. 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进行图形变换改变对象属性值
作用对象ImageViewView任意对象
是否改变实际属性
灵活性
性能消耗
适用场景简单序列动画View的简单动画复杂动画、自定义属性动画

五、建议

  1. 简单UI动画:优先考虑补间动画,实现简单且性能较好

  2. 复杂动画或需要交互:使用属性动画,功能更强大

  3. 小型的连续图片动画:可以使用帧动画

  4. 内存优化:帧动画要注意图片大小和数量,避免OOM

  5. 动画性能:避免在动画过程中执行耗时操作

  6. 动画复用:尽量使用XML定义动画,便于复用和维护

  7. 新项目:建议主要使用属性动画,功能最全面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值