三天快速学习 Flutter(三)之动画

好的!延续前两篇《三天快速学习 Flutter(一)基础与布局》和《(二)事件》"从使用的角度出发,只学最核心、最常用" 的高效风格,第三篇聚焦 动画(Animation)


太多教程繁琐、浪费时间。我们如果只从使用的角度出发,那么 Flutter 动画的学习曲线也可以大大缩短。记住这个公式:

布局解决能看到什么东西,事件决定能做什么事情,动画让布局和事件拥有更好的体验。

搞定这三样,就可以从事基本的开发了。本篇就带你用最短路径掌握 Flutter 动画的核心要点。

一、动画的本质:值的变化

在 Flutter 中,动画的本质不是直接操作 UI,而是驱动一个值(通常是 double 类型)随时间从一个状态平滑地变化到另一个状态。UI 组件监听这个值的变化,并据此重新绘制自己。

例如:

  • 驱动 opacity(透明度)从 1.0 变为 0.0,实现淡出效果。
  • 驱动 width(宽度)从 50.0 变为 200.0,实现伸展效果。
  • 驱动 color(颜色)从红色变为蓝色,实现颜色渐变。
二、最核心的两个概念:AnimationAnimationController

要实现动画,离不开这两个基石:

  1. AnimationController:动画的"总指挥"。

    • 它负责控制 动画的播放(forward())、暂停、反向播放(reverse())和停止。
    • 它内部持有一个从 0.01.0 的值(称为 value),代表动画的进度。
    • 创建时需要传入一个 vsync 参数(通常用 this,即当前 State 对象),用于防止屏幕外的动画消耗不必要的资源。
  2. Animation:动画的"值提供者"。

    • 它本身不控制动画,而是包装 AnimationController 的值,并可以对其应用插值器(Curves)类型转换
    • 最常用的 AnimationTween(补间动画),它可以将 0.0 - 1.0 的范围映射到你想要的任何数值范围(如 50.0 - 200.0)。
三、两种最常用、最简单的动画写法
1. 使用 AnimatedWidget (推荐新手)

这是最简洁的方式,它帮你自动处理了 StatefulWidget 的重建逻辑。

步骤:

  1. State 中创建 AnimationControllerAnimation(如 Tween)。
  2. initState 中初始化它们,并将 Tween 附加到 Controller 上。
  3. 使用 AnimatedContainer, AnimatedOpacity, AnimatedPadding 等预置的 AnimatedWidget,并将你的 Animation 对象赋给其属性。

示例:点击按钮,让一个容器的颜色和大小平滑变化。

复制代码
class MyAnimatedWidget extends StatefulWidget {
  @override
  _MyAnimatedWidgetState createState() => _MyAnimatedWidgetState();
}

class _MyAnimatedWidgetState extends State<MyAnimatedWidget> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _sizeAnimation;
  late Animation<Color?> _colorAnimation;

  @override
  void initState() {
    super.initState();
    // 1. 创建控制器
    _controller = AnimationController(
      duration: const Duration(seconds: 1),
      vsync: this,
    );

    // 2. 创建动画(Tween)
    _sizeAnimation = Tween<double>(begin: 50.0, end: 200.0).animate(_controller);
    _colorAnimation = ColorTween(begin: Colors.blue, end: Colors.red).animate(_controller);
  }

  @override
  void dispose() {
    _controller.dispose(); // 别忘了释放资源
    super.dispose();
  }

  void _toggleAnimation() {
    if (_controller.isCompleted) {
      _controller.reverse(); // 如果动画完成,就倒放
    } else {
      _controller.forward(); // 否则正向播放
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 3. 使用 AnimatedContainer,它会自动监听动画值并重建
        AnimatedContainer(
          width: _sizeAnimation.value,
          height: _sizeAnimation.value,
          color: _colorAnimation.value,
          duration: Duration.zero, // 因为我们用控制器控制,这里设为0
          curve: Curves.easeIn, // 可以在这里或在 animate() 里加曲线
        ),
        ElevatedButton(
          onPressed: _toggleAnimation,
          child: Text('开始/停止 动画'),
        ),
      ],
    );
  }
}
2. 使用 AnimatedBuilder

当你想对任意Widget 添加动画,或者动画逻辑比较复杂时,AnimatedBuilder 是更灵活的选择。

核心思想: AnimatedBuilder 会监听你传给它的 Animation 对象,一旦值发生变化,就只重建它的 builder 函数返回的部分 ,而不是整个父 Widget,性能更好。

示例:让一个文本的字体大小随动画变化。

复制代码
// ... (在 State 中同样需要 _controller 和 _sizeAnimation)

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      // 使用 AnimatedBuilder 包裹需要动画的部件
      AnimatedBuilder(
        animation: _sizeAnimation, // 监听这个动画
        builder: (context, child) {
          return Text(
            'Hello, Flutter!',
            style: TextStyle(fontSize: _sizeAnimation.value),
          );
        },
      ),
      ElevatedButton(
        onPressed: () {
          _controller.forward(from: 0.0); // 从头开始播放
        },
        child: Text('放大文字'),
      ),
    ],
  );
}
四、提升体验的关键:Curves(动画曲线)

默认的动画是线性匀速的,显得很机械。Curves 可以让你的动画拥有"生命感",比如先快后慢 (Curves.easeOut),或有弹性 (Curves.bounceInOut)。

使用方法: 在创建 Animation 时,通过 curve 参数指定。

复制代码
_sizeAnimation = Tween<double>(begin: 50.0, end: 200.0)
    .animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
五、总结:只需记住这几点
  1. 核心目标:动画就是让一个值平滑变化。
  2. 两大基石AnimationController(控制播放) + Animation/Tween(定义值的范围)。
  3. 两种写法
    • 简单场景用 AnimatedContainerAnimatedOpacity 等。
    • 复杂或自定义场景用 AnimatedBuilder
  4. 灵魂点缀 :用 Curves 让动画更自然。
  5. 别忘清理 :在 dispose 方法中调用 _controller.dispose()

搞定这些,你就已经掌握了 Flutter 动画 80% 的日常使用场景。剩下的,遇到具体需求再去查文档即可!

相关推荐
wuyk55522 分钟前
从零吃透Modbus通信|第7章:终极工程整合(模块化架构、双模式主机从机、RTOS适配、量产级模板)
c语言·stm32·学习·架构
卢锡荣1 小时前
国产PD3.1全集成Type-C管控芯片LDR6020P
c语言·开发语言
Freak嵌入式1 小时前
Pico UART 数据收发实战:硬件配置、MicroPython 编程
java·开发语言·单片机·嵌入式硬件·生活
Casual1 小时前
【网络基础进阶】:看懂子网划分与 VLAN
开发语言·网络·php
一条破秋裤1 小时前
STM32 学习笔记:PWM 驱动 LED 呼吸灯与舵机代码
笔记·stm32·学习
码农coding2 小时前
android12 开机动画分析
android
2501_915106322 小时前
安卓抓包软件2026,免证书抓包 应用层抓包 代理抓包全解析
网络协议·计算机网络·网络安全·ios·adb·https·udp
cfm_29142 小时前
线程池阻塞队列
java·开发语言
xxwxx__2 小时前
C++ list 深度解析:从使用原理到模拟实现
开发语言·c++·list
Chester_19992 小时前
CSP202303C.LDAP
开发语言·c++·蓝桥杯·stl