SwiftUI 系列 09|SwiftUI 动画入门:animation 与 withAnimation 的使用
真正要分清的是动画是附着在状态变化上,还是需要对一次具体变化显式包裹
SwiftUI 动画最容易给人一种“好像很简单”的感觉:
- 加个
.animation - 或者包个
withAnimation
页面就动起来了。
但真实项目里,动画最容易出问题的地方恰恰就在这里:
- 这里也跟着动了
- 不该动的地方动了
- 某次状态变化没有动画
- 列表刷新时动画特别怪
这说明很多时候我们是没有先搞清:
这次动画到底是应该附着在某种状态变化上,还是应该只包裹某一次具体的变化过程。
一、SwiftUI 动画的核心是“让状态变化被插值呈现”
这点特别重要。
如果还是用 UIKit 思路去理解动画,很容易默认:
- 我要让某个控件动起来
而 SwiftUI 更像是在做:
- 当状态从 A 变成 B 时,用动画把这个变化过程表达出来
这意味着动画天然依附于状态变化。 所以真正要判断的是:
- 哪个状态变化值得被动画化
- 动画作用范围应该多大
二、.animation 和 withAnimation 的差别,不只是写法不同,而是控制粒度不同
一个更实用的理解是:
.animation更像给某类状态变化附加动画倾向withAnimation更像对某一次明确的状态修改做显式包裹
所以当用 .animation 时,更像是在说:
这块视图对于某些状态变化,应该默认有动画反应。
而 withAnimation 更像是在说:
我现在要做这次状态修改,并且希望这次修改被动画化。
这个区别很关键,因为它会直接影响动画的可控性。
三、很多页面动画会“莫名其妙一起动”
最常见的原因就是作用范围没收住。
例如本来只想让一个展开区块带动画,结果:
- 同层其他文本也跟着动
- 父容器高度变化导致整个区域都有动画
- 某些不相关布局也开始过渡
这通常是把动画附着在了一个范围过大的状态变化或视图层级上。
所以动画写乱时,我最常回头检查的是:
- 当前这层到底负责什么变化
- 动画是不是绑在了过大的视图范围上
- 状态变化是不是同时影响了太多布局结果
四、很多“动画不好看”,根本是状态建模不清
有些动画看起来别扭,并是:
- 状态本身设计得不清楚
- 一次变化同时改了太多值
- 页面布局层级不稳定
比如一次点击同时触发:
- 展开
- 文案切换
- 高度变化
- 列表重排
那最终看起来很乱,往往是让太多不同语义的变化挤在同一次状态跳变里了。
五、什么时候更适合用 withAnimation
我更倾向于在这些场景里用它:
- 某个用户动作触发了一次明确的状态切换
- 我只希望这一次状态改动被动画化
- 我想显式控制“这次变化要不要动”
比如:
- 展开 / 收起
- 插入 / 删除一个局部区块
- 点击后切换某个呈现状态
它的好处是语义更清楚: 知道动画是和这次动作直接绑定的。
六、什么时候 .animation 容易更危险
当没有先想清楚状态影响范围时,.animation 特别容易把页面变得“哪里都在微微动”。
尤其在复杂布局里,如果一个状态变化会影响:
- 尺寸
- 对齐
- 文案
- 容器层级
那把动画直接挂在上面,很容易导致整个区域都跟着过渡。
所以 .animation是更适合那些:
- 影响范围相对明确
- 状态变化语义单纯
- 局部区域稳定
的场景。
七、一个更实用的判断:这次动画是在表达“一个动作”,还是在默认修饰“一类变化”
如果是在表达一个明确动作:
- 点开
- 收起
- 插入
- 删除
那我通常更先考虑 withAnimation。
如果是在修饰一类稳定的局部状态变化,才更容易考虑 .animation。
这个判断很有用,因为它让不会只盯着 API 名字,而是真正回到“动画语义”本身。
八、结论:SwiftUI 动画真正要分清的,是状态变化的边界和动画作用的边界
换个更短的说法,我会说:
SwiftUI 动画最重要的是先分清:这次动画到底是在表达某次明确动作,还是在给某类局部状态变化附加过渡效果。
一旦这两个边界清楚了,动画就会更可控; 边界不清,页面就很容易变成“到处都在动,但没有一个地方动得特别对”。