最近在项目里接触到了一些比较复杂的界面动效,就抽空把 Android 的动画系统重新整理了一遍。虽然动画这一块看起来“花哨”,但它其实牵扯到的知识面还挺多,比如视图属性、绘制流程、性能优化等等。下面就按照我自己的理解做个记录,也欢迎大家指出错误或分享更好的实践方式。


一、动画的分类整理(以实际开发角度)

Android 的动画系统总体可以分为以下几类:

类型 API 类 简述
视图动画 View Animation(即 Tween Animation) 传统动画,只改变视图的显示效果,不改变实际属性
帧动画 AnimationDrawable 一帧一帧地播放图像,类似幻灯片
属性动画 ObjectAnimator / AnimatorSet 改变对象的属性值(如 translationX
物理动画 SpringAnimation / FlingAnimation 更加真实的动画模型,引入弹性、摩擦力等

二、属性动画实践小记

属性动画是我用得最多的,毕竟现在项目对交互的“真实感”要求越来越高了。

基本用法(ObjectAnimator)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
animator.setDuration(1000);
animator.start();
````

* 这里 `"alpha"` 就是属性名,其实底层会调用 `setAlpha()` 方法。
* 如果属性没有 setter/getter,就得自己写个包装类。

### 动画组合(AnimatorSet)

```java
ObjectAnimator moveX = ObjectAnimator.ofFloat(view, "translationX", 0f, 300f);
ObjectAnimator fade = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f);
AnimatorSet set = new AnimatorSet();
set.playTogether(moveX, fade);
set.setDuration(1000);
set.start();

⚠️ 实际项目里如果是 RecyclerView 中大批量启动动画,要注意性能影响。


三、值动画 ValueAnimator 用法

虽然 ObjectAnimator 更直接,但 ValueAnimator 更灵活,可以用来控制任意值的变化。

1
2
3
4
5
6
7
ValueAnimator animator = ValueAnimator.ofInt(0, 100);
animator.setDuration(1000);
animator.addUpdateListener(animation -> {
int value = (int) animation.getAnimatedValue();
view.setTranslationX(value);
});
animator.start();

四、Transition 框架(适合做页面切换动画)

这是在 API 21+ 引入的一个动画过渡系统,适用于 Activity/Fragment 切换。

1
2
3
4
5
// 使用 Fade 动画进行布局淡入淡出
Transition fade = new Fade();
fade.setDuration(300);
TransitionManager.beginDelayedTransition(container, fade);
view.setVisibility(View.GONE); // 自动平滑消失

📌 注意:要配合 TransitionManager 使用,布局必须提前发生变化。


五、物理动画(Spring / Fling)

有些交互动画用属性动画显得太“死板”了,比如弹簧滑动、卡片回弹,可以试试物理动画。

1
2
3
4
SpringAnimation springAnim = new SpringAnimation(view, SpringAnimation.TRANSLATION_Y, 0);
springAnim.getSpring().setStiffness(SpringForce.STIFFNESS_LOW);
springAnim.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY);
springAnim.start();

用起来确实自然不少,但也要注意数值调参问题,很容易“弹飞”。


六、容易忽视的一些点

  • 视图动画 VS 属性动画区别:前者只是“表象”,不改变 View 实际坐标,比如点击事件区域不变;属性动画是“真实”的。
  • 性能调优:动画尽量避免同时更改多个复杂属性(如 scale + alpha + translation),而且需要关闭 GPU 硬件加速时要测试。
  • 动画取消问题:有些动画可能被用户打断,记得及时调用 cancel(),或者用 addListener() 判断状态。

七、小结 + 疑问

虽然动画是 UI 体验的“加分项”,但我现在也越来越觉得:动画≠炫酷,而是为了 引导用户注意力建立操作反馈

本篇主要是我个人学习与整理过程,很多实现细节还有待深入(比如贝塞尔曲线、插值器曲线设计、FrameCallback 精度控制等),后面有空也会继续补上。


如果你对某些动画实现方式有更优解,或者发现我哪里写错了,非常欢迎留言交流,我也会持续更新这类笔记。