三天快速学习 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% 的日常使用场景。剩下的,遇到具体需求再去查文档即可!

相关推荐
雨季6665 小时前
Flutter 三端应用实战:OpenHarmony 简易“动态主题切换卡片”交互模式
flutter·ui·交互·dart
lxl13075 小时前
学习C++(5)运算符重载+赋值运算符重载
学习
5 小时前
java关于内部类
java·开发语言
好好沉淀5 小时前
Java 项目中的 .idea 与 target 文件夹
java·开发语言·intellij-idea
lsx2024065 小时前
FastAPI 交互式 API 文档
开发语言
VCR__5 小时前
python第三次作业
开发语言·python
向哆哆5 小时前
构建健康档案管理快速入口:Flutter × OpenHarmony 跨端开发实战
flutter·开源·鸿蒙·openharmony·开源鸿蒙
码农水水5 小时前
得物Java面试被问:消息队列的死信队列和重试机制
java·开发语言·jvm·数据结构·机器学习·面试·职场和发展
wkd_0075 小时前
【Qt | QTableWidget】QTableWidget 类的详细解析与代码实践
开发语言·qt·qtablewidget·qt5.12.12·qt表格
清蒸鳜鱼5 小时前
【Mobile Agent——Droidrun】MacOS+Android配置、使用指南
android·macos·mobileagent