引言
在Android开发中,动画是提升用户体验的核心技术之一。Android提供了**补间动画(Tween Animation)和属性动画(Property Animation)**两种主要动画框架。本文将从原理剖析、代码实现、使用步骤、对比总结等多个维度深入讲解这两种动画技术,帮助你彻底掌握它们的核心机制与应用场景。
一、补间动画(Tween Animation)
1.1 核心原理
补间动画通过视图的绘制矩阵变换 实现视觉效果,但不会改变View的实际属性 。其本质是对View
的Canvas
应用Matrix
变换(如平移、缩放、旋转),在每次绘制时重新计算位置,从而实现动画效果。
实现流程:
- 定义动画参数:指定动画类型(平移、缩放等)、持续时间、插值器等。
- 逐帧计算:系统根据时间进度计算当前变换参数。
- 重绘视图 :通过
View.invalidate()
触发重绘,应用变换矩阵。
1.2 代码实现(XML + Java)
步骤1:定义XML动画资源
在res/anim/
目录下创建动画文件(如translate_anim.xml
):
xml
<!-- 平移动画 -->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="0%"
android:toXDelta="100%"
android:interpolator="@android:anim/linear_interpolator"/>
步骤2:加载并启动动画
java
Animation anim = AnimationUtils.loadAnimation(this, R.anim.translate_anim);
view.startAnimation(anim);
// 监听动画事件
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
// 动画结束后,View的实际位置未改变!
Log.d("TweenAnim", "View位置: (" + view.getX() + ", " + view.getY() + ")");
}
@Override
public void onAnimationRepeat(Animation animation) {}
});
1.3 补间动画的四种类型
类型 | XML标签 | 核心属性 |
---|---|---|
平移 | <translate> |
fromXDelta , toXDelta |
缩放 | <scale> |
fromXScale , toXScale |
旋转 | <rotate> |
fromDegrees , toDegrees |
透明度 | <alpha> |
fromAlpha , toAlpha |
二、属性动画(Property Animation)
2.1 核心原理
属性动画通过动态修改目标对象的属性值 实现动画,支持任意对象(不仅仅是View
)。其核心类为ValueAnimator
和ObjectAnimator
,底层通过Choreographer
监听VSYNC信号实现帧同步。
实现流程:
- 属性值计算 :
ValueAnimator
根据时间插值器和类型估值器计算当前属性值。 - 属性更新 :通过反射或
setter
方法将计算的值应用到目标对象。 - 重绘机制 :若目标对象是
View
,自动调用invalidate()
触发重绘。
2.2 代码实现
示例1:使用ObjectAnimator平移动画
java
// 水平平移100px
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 0f, 100f);
animator.setDuration(1000);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.start();
// 监听属性变化
animator.addUpdateListener(animation -> {
float value = (float) animation.getAnimatedValue();
Log.d("PropertyAnim", "当前translationX值: " + value);
});
示例2:自定义ValueAnimator
java
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
valueAnimator.addUpdateListener(animation -> {
int value = (int) animation.getAnimatedValue();
// 手动更新View属性(如宽度)
view.getLayoutParams().width = value;
view.requestLayout();
});
valueAnimator.start();
2.3 高级用法:组合动画与自定义估值器
组合动画(AnimatorSet)
java
ObjectAnimator moveX = ObjectAnimator.ofFloat(view, "translationX", 0f, 100f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);
AnimatorSet set = new AnimatorSet();
set.playTogether(moveX, rotate); // 或 playSequentially()
set.setDuration(1000);
set.start();
自定义TypeEvaluator(实现颜色渐变)
java
public class ColorEvaluator implements TypeEvaluator<Integer> {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startA = (startValue >> 24) & 0xff;
int startR = (startValue >> 16) & 0xff;
// 计算中间颜色值...
return Color.argb(startA, (int)(startR + fraction * (endR - startR)), ...);
}
}
ValueAnimator colorAnim = ValueAnimator.ofObject(new ColorEvaluator(), Color.RED, Color.BLUE);
colorAnim.addUpdateListener(animator -> view.setBackgroundColor((int) animator.getAnimatedValue()));
colorAnim.start();
三、属性动画 vs 补间动画:关键对比
对比维度 | 补间动画 | 属性动画 |
---|---|---|
作用对象 | 仅支持View |
任意对象(包括非View ) |
属性修改 | 仅视觉变化,不改变实际属性 | 真实修改对象属性值 |
点击事件位置 | 停留在原始位置 | 随动画位置变化 |
动画类型 | 四种固定类型(平移、缩放、旋转、透明度) | 支持任意属性,可自定义 |
性能 | 较低(依赖频繁重绘) | 较高(直接修改属性,减少冗余计算) |
灵活性 | 功能有限,不支持组合动画 | 支持组合、路径动画、动态估值器等 |
四、使用步骤总结
补间动画使用步骤:
- 定义XML动画文件 :在
res/anim/
中编写动画参数。 - 加载动画 :
AnimationUtils.loadAnimation()
。 - 启动动画 :
view.startAnimation(anim)
。 - 监听事件 :通过
AnimationListener
处理回调。
属性动画使用步骤:
- 创建Animator对象 :
ObjectAnimator.ofFloat()
或ValueAnimator.ofInt()
。 - 设置参数:时长、插值器、重复模式等。
- 添加监听器 :
addUpdateListener()
或addListener()
。 - 启动动画 :
animator.start()
。
五、关键点总结
-
补间动画的局限性:
- 点击事件位置不更新,无法实现复杂动画。
- 仅适用于
View
,无法修改非绘制属性。
-
属性动画的核心优势:
- 真实修改属性值,支持任意对象。
- 通过
Choreographer
实现60fps流畅动画。 - 强大的扩展能力(如路径动画、ViewPropertyAnimator)。
-
性能优化建议:
- 避免在动画过程中执行耗时操作。
- 使用硬件加速(
android:hardwareAccelerated="true"
)。 - 对复杂动画使用
ViewPropertyAnimator
简化代码。
六、实际应用场景
补间动画适用场景:
- 简单的视图过渡效果(如渐隐渐现)。
- 无需交互变化的静态动画。
属性动画适用场景:
- 需要跟随动画更新的交互(如拖拽控件)。
- 自定义复杂动画(如曲线运动、动态颜色变化)。
- 非
View
对象的动画(如修改RecyclerView
的Item数据)。
七、常见问题与解决方案
Q1:补间动画后View的点击区域错误怎么办?
答 :改用属性动画修改实际属性(如translationX
),或手动更新View的位置。
Q2:属性动画导致内存泄漏如何避免?
答 :在onDestroy()
中调用animator.cancel()
,避免持有Activity的引用。
Q3:如何实现动画的暂停与恢复?
答 :属性动画可通过animator.pause()
和animator.resume()
控制。
结语
属性动画是Android动画的现代化解决方案,几乎可以完全替代补间动画。理解其底层原理和灵活应用,能够显著提升应用的交互体验。建议在实际开发中优先选择属性动画,同时结合ViewPropertyAnimator
和AnimatorSet
简化代码。