1. 动画基础概念:Android动画体系概述、View动画与Compose动画的对比、动画的本质与帧率
各位同学好,我是你们的老朋友。今天咱们开始聊动画——Android动画的演进之路。说实话,动画这块我踩过不少坑,也见证了整个体系从View到Compose的变迁。这一章我们先打好基础,把动画的核心概念理清楚。
1.1 动画的本质:说白了就是“视觉欺骗”
动画的本质是什么?我个人的理解很简单:在一段时间内,让视觉元素的状态连续变化。你想想看,电影24帧/秒,我们觉得流畅;游戏60帧/秒,我们觉得丝滑。其实每一帧都是静态的,只是变化够快,人眼就产生了“动”的错觉。
在Android里,动画就是控制View或Composable的属性(位置、大小、透明度、颜色等)随时间变化。这个变化不是跳变的,而是连续的——至少看起来是连续的。
核心公式:
动画 = 属性值 × 时间函数 × 帧率
属性值决定“变什么”,时间函数决定“怎么变”,帧率决定“多流畅”。
1.2 帧率:60fps是底线,120fps是追求
帧率(FPS,Frames Per Second)就是每秒刷新的画面数。Android系统默认是60fps,也就是每16.6ms刷新一帧。如果一帧的绘制时间超过16.6ms,就会掉帧——画面卡顿。
我记得有一次做列表动画,明明动画逻辑没问题,但就是卡。后来发现是布局层级太深,measure/layout耗时太长。嗯,这里要注意:动画卡顿不一定是动画代码的问题,很可能是UI渲染的瓶颈。
| 帧率 | 每帧耗时 | 体验 |
|---|---|---|
| 30fps | 33.3ms | 明显卡顿,不可接受 |
| 60fps | 16.6ms | 流畅,Android标准 |
| 90fps | 11.1ms | 很流畅,高端机标配 |
| 120fps | 8.3ms | 丝滑,但功耗高 |
避坑指南:我曾经在低端机上跑60fps的动画,结果掉帧到30fps。后来发现是动画中做了大量对象创建。解决方案:用对象池复用,或者用属性动画的ValueAnimator配合setFrameDelay()控制帧率。
1.3 Android动画体系:三驾马车
Android的动画体系,说白了就是三套东西:
- View动画(补间动画):老牌选手,Android 1.0就有了。只能对View做平移、缩放、旋转、透明度。不能改变View的真实位置——你看着它动了,但点击事件还在原地。我当年刚入行时就被这个坑过。
- 属性动画(Property Animation):Android 3.0引入,解决了View动画的痛点。可以改变任意对象的任意属性,而且是真的改变了。比如移动一个Button,它的点击区域也跟着走。
- Compose动画:Jetpack Compose时代的产物,声明式动画。你不需要告诉系统“怎么动”,只需要告诉系统“最终状态是什么”,系统自动帮你插值。
这三者不是替代关系,而是演进关系。View动画虽然老,但简单场景下依然好用;属性动画是View系统的中坚力量;Compose动画则是未来趋势。
1.4 View动画 vs Compose动画:一场对比
我经常被问到:“老师,现在学View动画还有用吗?”我的回答是:有用,但优先级要往后放。如果你维护的是老项目,View动画逃不掉;如果你新项目用Compose,那直接学Compose动画就行。
咱们直接看对比:
| 维度 | View动画 | Compose动画 |
|---|---|---|
| 编程范式 | 命令式(告诉系统每一步怎么动) | 声明式(告诉系统最终状态) |
| 可动画属性 | 仅限View的4种属性(平移/缩放/旋转/透明度) | 任意Composable的任意属性 |
| 真实位置 | 不改变(点击区域还在原地) | 改变(Composable真的移动了) |
| 性能 | 依赖View层级,层级深则卡 | 基于Compose的智能重组,性能更优 |
| 代码量 | 较多(需要写监听器、插值器等) | 较少(几行代码搞定) |
| 学习曲线 | 平缓(概念简单) | 陡峭(需要理解Compose状态管理) |
注意:View动画的fillAfter属性是个坑。你设置了fillAfter="true",动画结束后View看起来在终点,但点击事件还在起点。我曾经因为这个被测试妹子追着问:“为什么我点不到那个按钮?”
1.5 动画的核心三要素:时长、插值器、重复行为
不管哪种动画,都离不开这三个东西:
- 时长(Duration):动画持续多久。太短看不清,太长显得拖沓。我个人习惯:入场动画300ms,退场动画200ms,交互反馈100ms。
- 插值器(Interpolator):控制动画的快慢节奏。比如
LinearInterpolator是匀速,AccelerateDecelerateInterpolator是两头慢中间快。我建议:不要用匀速,太生硬了。 - 重复行为(Repeat):动画是否重复、重复几次、是否反向。比如加载中的旋转动画,一般设置无限重复。
你想想看,这三个要素组合起来,就能产生千变万化的动画效果。比如一个按钮点击后的反馈:100ms的缩放动画,配合OvershootInterpolator,会有一个“弹一下”的效果,用户会觉得这个按钮很有“弹性”。
1.6 本章知识体系总览
下面我用一张图来总结本章的核心内容。这张图展示了Android动画体系的整体结构,以及View动画和Compose动画在其中的位置。
这张图把整个体系串起来了。从底层的动画本质,到上层的三种实现方式,再到最核心的三要素。你记住这个结构,后面学起来就清晰了。
1.7 小结:这一章你该带走什么?
嗯,这一章的内容就到这里。我帮你梳理一下重点:
- 动画的本质是属性随时间连续变化,帧率决定了流畅度,60fps是底线。
- Android动画三驾马车:View动画(老但简单)、属性动画(中坚力量)、Compose动画(未来趋势)。
- View动画和Compose动画的核心区别:命令式 vs 声明式,是否改变真实位置。
- 三要素:时长、插值器、重复行为,掌握它们就能控制动画的节奏和效果。
下一章,我们会深入View动画的细节,看看那些经典的Animation类到底怎么用,以及我当年是怎么用错setFillAfter被测试追着打的。咱们下章见。