动画组件详解

动画是提升用户体验的关键。Flutter 提供了强大的动画系统,可以轻松创建流畅的动画效果。本教程将详细介绍动画组件和最佳实践。

重要提示:Flutter 3.28+ 进一步优化了动画性能,Impeller 渲染引擎让动画更加流畅。

1. AnimatedContainer 隐式动画

AnimatedContainer 是最简单的动画组件,自动处理属性变化。

📐 AnimatedContainer 动画效果

状态A

状态B

属性变化时自动产生过渡动画 (duration: 300ms)

class AnimatedContainerExample extends StatefulWidget {
  const AnimatedContainerExample({super.key});

  @override
  State createState() =>
      _AnimatedContainerExampleState();
}

class _AnimatedContainerExampleState extends State {
  double _width = 100;
  double _height = 100;
  Color _color = Colors.blue;
  BorderRadiusGeometry _borderRadius = BorderRadius.circular(8);

  void _changeProperties() {
    setState(() {
      _width = _width == 100 ? 200 : 100;
      _height = _height == 100 ? 200 : 100;
      _color = _color == Colors.blue ? Colors.red : Colors.blue;
      _borderRadius = _borderRadius == BorderRadius.circular(8)
          ? BorderRadius.circular(50)
          : BorderRadius.circular(8);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          AnimatedContainer(
            width: _width,
            height: _height,
            decoration: BoxDecoration(
              color: _color,
              borderRadius: _borderRadius,
            ),
            duration: const Duration(seconds: 1),
            curve: Curves.fastOutSlowIn,
          ),
          const SizedBox(height: 20),
          ElevatedButton(
            onPressed: _changeProperties,
            child: const Text('改变属性'),
          ),
        ],
      ),
    );
  }
}

2. AnimationController 显式动画

使用 AnimationController 创建更复杂的动画。

📐 AnimationController 动画生命周期

0.0
开始
0.5
1.0
结束

forward()

reverse()

repeat()

stop()

value 从 0.0 到 1.0,支持 forward/reverse/repeat/stop 操作

class AnimationControllerExample extends StatefulWidget {
  const AnimationControllerExample({super.key});

  @override
  State createState() =>
      _AnimationControllerExampleState();
}

class _AnimationControllerExampleState
    extends State
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );

    _animation = Tween(
      begin: 0,
      end: 300,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeInOut,
    ));

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
        animation: _animation,
        builder: (context, child) {
          return Container(
            width: _animation.value,
            height: _animation.value,
            color: Colors.blue,
          );
        },
      ),
    );
  }
}

3. Tween 动画插值

Tween 用于定义动画的起始值和结束值。

📐 Tween 插值类型

ColorTween (颜色)

SizeTween (大小)

Tween<Offset> (位置)

Tween<double> (数值)

0.0 0.5 1.0

Tween 定义动画的 begin 和 end 值,自动计算中间值

// 颜色动画
Animation colorAnimation = ColorTween(
  begin: Colors.blue,
  end: Colors.red,
).animate(_controller);

// 大小动画
Animation sizeAnimation = SizeTween(
  begin: const Size(100, 100),
  end: const Size(200, 200),
).animate(_controller);

// 位置动画
Animation offsetAnimation = Tween(
  begin: Offset.zero,
  end: const Offset(100, 100),
).animate(_controller);

// 使用颜色动画
AnimatedBuilder(
  animation: colorAnimation,
  builder: (context, child) {
    return Container(
      width: 100,
      height: 100,
      color: colorAnimation.value,
    );
  },
)

4. FadeTransition 淡入淡出

实现透明度变化的动画。

📐 FadeTransition 透明度变化

opacity: 0.0

Flutter

opacity: 0.3

Flutter

opacity: 0.6

Flutter

opacity: 1.0

Flutter

opacity 从 0.0 到 1.0,实现淡入淡出效果

class FadeTransitionExample extends StatefulWidget {
  const FadeTransitionExample({super.key});

  @override
  State createState() =>
      _FadeTransitionExampleState();
}

class _FadeTransitionExampleState extends State
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );

    _animation = CurvedAnimation(
      parent: _controller,
      curve: Curves.easeIn,
    );

    _controller.repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: FadeTransition(
        opacity: _animation,
        child: const FlutterLogo(
          size: 100,
        ),
      ),
    );
  }
}

5. SlideTransition 滑动动画

实现位置滑动的动画。

📐 SlideTransition 位置滑动

Offset(-1, 0)

Offset(-0.5, 0)

Offset(0, 0)

从屏幕外滑入,Offset 范围从 (-1, 0) 到 (0, 0)

class SlideTransitionExample extends StatefulWidget {
  const SlideTransitionExample({super.key});

  @override
  State createState() =>
      _SlideTransitionExampleState();
}

class _SlideTransitionExampleState extends State
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 1),
      vsync: this,
    );

    _animation = Tween(
      begin: const Offset(-1, 0),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeInOut,
    ));

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: _animation,
      child: const Center(
        child: FlutterLogo(size: 100),
      ),
    );
  }
}

6. ScaleTransition 缩放动画

实现大小缩放的动画。

📐 ScaleTransition 大小缩放

scale: 0.5

Flutter

scale: 0.8

Flutter

scale: 1.0

Flutter

scale: 1.2

Flutter

scale 从 0 到 1+,实现从小到大的缩放效果

class ScaleTransitionExample extends StatefulWidget {
  const ScaleTransitionExample({super.key});

  @override
  State createState() =>
      _ScaleTransitionExampleState();
}

class _ScaleTransitionExampleState extends State
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 1),
      vsync: this,
    );

    _animation = CurvedAnimation(
      parent: _controller,
      curve: Curves.elasticOut,
    );

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ScaleTransition(
        scale: _animation,
        child: const FlutterLogo(size: 100),
      ),
    );
  }
}

7. RotationTransition 旋转动画

实现旋转的动画。

📐 RotationTransition 旋转效果

turns: 0.0

turns: 0.25

turns: 0.5

turns: 0.75

turns: 1.0

turns 从 0.0 到 1.0 表示旋转 0° 到 360°

class RotationTransitionExample extends StatefulWidget {
  const RotationTransitionExample({super.key});

  @override
  State createState() =>
      _RotationTransitionExampleState();
}

class _RotationTransitionExampleState extends State
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );

    _animation = CurvedAnimation(
      parent: _controller,
      curve: Curves.linear,
    );

    _controller.repeat();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: RotationTransition(
        turns: _animation,
        child: const FlutterLogo(size: 100),
      ),
    );
  }
}

8. StaggeredAnimation 交错动画

实现多个动画按顺序执行。

📐 StaggeredAnimation 动画序列

0.0 - 0.3
淡入
0.3 - 0.6
缩放
0.6 - 1.0
滑动

步骤 1: 淡入

🎯

步骤 2: 缩放

🎯

步骤 3: 滑动

🎯

使用 Interval 控制每个动画的执行时间,实现序列效果

class StaggeredAnimationExample extends StatefulWidget {
  const StaggeredAnimationExample({super.key});

  @override
  State createState() =>
      _StaggeredAnimationExampleState();
}

class _StaggeredAnimationExampleState extends State
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _fadeAnimation;
  late Animation _scaleAnimation;
  late Animation _slideAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this,
    );

    _fadeAnimation = Tween(begin: 0, end: 1).animate(
      CurvedAnimation(parent: _controller, curve: const Interval(0, 0.3)),
    );

    _scaleAnimation = Tween(begin: 0.5, end: 1).animate(
      CurvedAnimation(parent: _controller, curve: const Interval(0.3, 0.6)),
    );

    _slideAnimation = Tween(begin: 100, end: 0).animate(
      CurvedAnimation(parent: _controller, curve: const Interval(0.6, 1)),
    );

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Opacity(
          opacity: _fadeAnimation.value,
          child: Transform.translate(
            offset: Offset(0, _slideAnimation.value),
            child: Transform.scale(
              scale: _scaleAnimation.value,
              child: const FlutterLogo(size: 100),
            ),
          ),
        );
      },
    );
  }
}

🔀 动画实现流程图

开始动画
动画类型?
简单属性
Animated*
复杂控制
AnimationController
过渡动画
Hero
完成动画

📊 动画类型对比

Flutter 动画类型对比表
类型 控制 复杂度 使用场景
Animated* 隐式 简单 属性动画
AnimationController 显式 复杂 自定义动画
Hero 隐式 中等 页面过渡
Transition* 显式 中等 过渡动画
Staggered 显式 复杂 序列动画

动画最佳实践

  • 优先使用隐式动画(Animated*)简单场景
  • 使用显式动画(AnimationController)处理复杂动画
  • 始终记得在 dispose 中释放 AnimationController
  • 使用合适的曲线让动画更自然
  • 避免在 build 方法中创建 AnimationController
  • 使用 AnimatedBuilder 减少重建范围
  • 合理设置动画时长,避免过长或过短
  • 使用 Hero 动画实现页面间共享元素过渡
性能提示:使用 const 构造函数和不透明的组件可以提高动画性能。
下一步:掌握动画组件后,继续学习第三方组件。