flutter-animations

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Flutter Animations

Flutter 动画

Overview

概述

Create smooth, performant animations in Flutter using the right approach for each use case. This skill covers complete animation workflow: from choosing between implicit/explicit approaches to implementing complex effects like hero transitions and staggered animations.
针对不同使用场景采用合适的方法,在Flutter中创建流畅、高性能的动画。本指南涵盖完整的动画工作流程:从选择隐式/显式实现方式,到实现Hero过渡、交错动画等复杂效果。

Animation Type Decision Tree

动画类型决策树

Choose the right animation type based on your requirements:
Implicit Animations - Use when:
  • Animating a single property (color, size, position)
  • Animation is triggered by state change
  • No need for fine-grained control
Explicit Animations - Use when:
  • Need full control over animation lifecycle
  • Animating multiple properties simultaneously
  • Need to react to animation state changes
  • Creating custom animations or transitions
Hero Animations - Use when:
  • Sharing an element between two screens
  • Creating shared element transitions
  • User expects element to "fly" between routes
Staggered Animations - Use when:
  • Multiple animations should run sequentially or overlap
  • Creating ripple effects or sequential reveals
  • Animating list items in sequence
Physics-Based Animations - Use when:
  • Animations should feel natural/physical
  • Spring-like behavior, scrolling gestures
  • Draggable interactions
根据需求选择合适的动画类型:
隐式动画 - 适用于以下场景:
  • 为单个属性(颜色、尺寸、位置)添加动画
  • 动画由状态变化触发
  • 无需细粒度控制
显式动画 - 适用于以下场景:
  • 需要完全控制动画生命周期
  • 同时为多个属性添加动画
  • 需要响应动画状态变化
  • 创建自定义动画或过渡效果
Hero动画 - 适用于以下场景:
  • 在两个页面之间共享某个元素
  • 创建共享元素过渡效果
  • 用户期望元素在页面间“飞动”
交错动画 - 适用于以下场景:
  • 多个动画需要按顺序执行或重叠
  • 创建涟漪效果或顺序展示动画
  • 为列表项添加顺序动画
基于物理的动画 - 适用于以下场景:
  • 动画需要呈现自然的物理效果
  • 弹簧式行为、滚动手势
  • 可拖拽交互

Implicit Animations

隐式动画

Implicit animations automatically handle the animation when properties change. No controller needed.
当属性发生变化时,隐式动画会自动处理动画过程,无需控制器。

Common Implicit Widgets

常用隐式组件

AnimatedContainer - Animates multiple properties (size, color, decoration, padding):
dart
AnimatedContainer(
  duration: const Duration(milliseconds: 300),
  curve: Curves.easeInOut,
  width: _expanded ? 200 : 100,
  height: _expanded ? 200 : 100,
  color: _expanded ? Colors.blue : Colors.red,
  child: const FlutterLogo(),
)
AnimatedOpacity - Simple fade animation:
dart
AnimatedOpacity(
  opacity: _visible ? 1.0 : 0.0,
  duration: const Duration(milliseconds: 300),
  child: const Text('Hello'),
)
TweenAnimationBuilder - Custom tween animation without boilerplate:
dart
TweenAnimationBuilder<double>(
  tween: Tween<double>(begin: 0, end: 1),
  duration: const Duration(seconds: 1),
  builder: (context, value, child) {
    return Opacity(
      opacity: value,
      child: Transform.scale(
        scale: value,
        child: child,
      ),
    );
  },
  child: const FlutterLogo(),
)
Other implicit widgets:
  • AnimatedPadding
    - Padding animation
  • AnimatedPositioned
    - Position animation (in Stack)
  • AnimatedAlign
    - Alignment animation
  • AnimatedContainer
    - Multiple properties
  • AnimatedSwitcher
    - Cross-fade between widgets
  • AnimatedDefaultTextStyle
    - Text style animation
AnimatedContainer - 为多个属性(尺寸、颜色、装饰、内边距)添加动画:
dart
AnimatedContainer(
  duration: const Duration(milliseconds: 300),
  curve: Curves.easeInOut,
  width: _expanded ? 200 : 100,
  height: _expanded ? 200 : 100,
  color: _expanded ? Colors.blue : Colors.red,
  child: const FlutterLogo(),
)
AnimatedOpacity - 简单的淡入淡出动画:
dart
AnimatedOpacity(
  opacity: _visible ? 1.0 : 0.0,
  duration: const Duration(milliseconds: 300),
  child: const Text('Hello'),
)
TweenAnimationBuilder - 无需样板代码的自定义补间动画:
dart
TweenAnimationBuilder<double>(
  tween: Tween<double>(begin: 0, end: 1),
  duration: const Duration(seconds: 1),
  builder: (context, value, child) {
    return Opacity(
      opacity: value,
      child: Transform.scale(
        scale: value,
        child: child,
      ),
    );
  },
  child: const FlutterLogo(),
)
其他隐式组件:
  • AnimatedPadding
    - 内边距动画
  • AnimatedPositioned
    - 位置动画(在Stack中使用)
  • AnimatedAlign
    - 对齐动画
  • AnimatedContainer
    - 多属性动画
  • AnimatedSwitcher
    - 组件间交叉淡入淡出
  • AnimatedDefaultTextStyle
    - 文本样式动画

Best Practices

最佳实践

  • Prefer implicit animations for simple cases
  • Use appropriate curves for natural motion (see
    Curves
    class)
  • Set
    curve
    and
    duration
    for predictable behavior
  • Use
    onEnd
    callback when needed
  • Avoid nested implicit animations for performance
  • 简单场景优先使用隐式动画
  • 使用合适的曲线实现自然动效(参考
    Curves
    类)
  • 设置
    curve
    duration
    以保证行为可预测
  • 必要时使用
    onEnd
    回调
  • 避免嵌套隐式动画以保证性能

Explicit Animations

显式动画

Explicit animations provide full control with AnimationController.
显式动画通过AnimationController提供完全控制。

Core Components

核心组件

AnimationController - Drives the animation:
dart
late AnimationController _controller;


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


void dispose() {
  _controller.dispose();
  super.dispose();
}
Tween - Interpolates between begin and end values:
dart
animation = Tween<double>(begin: 0, end: 300).animate(_controller);
CurvedAnimation - Applies a curve to the animation:
dart
animation = CurvedAnimation(
  parent: _controller,
  curve: Curves.easeInOut,
);
AnimationController - 驱动动画:
dart
late AnimationController _controller;


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


void dispose() {
  _controller.dispose();
  super.dispose();
}
Tween - 在起始值和结束值之间插值:
dart
animation = Tween<double>(begin: 0, end: 300).animate(_controller);
CurvedAnimation - 为动画应用曲线:
dart
animation = CurvedAnimation(
  parent: _controller,
  curve: Curves.easeInOut,
);

AnimatedWidget Pattern

AnimatedWidget 模式

Best for reusable animated widgets:
dart
class AnimatedLogo extends AnimatedWidget {
  const AnimatedLogo({super.key, required Animation<double> animation})
    : super(listenable: animation);

  
  Widget build(BuildContext context) {
    final animation = listenable as Animation<double>;
    return Center(
      child: Container(
        height: animation.value,
        width: animation.value,
        child: const FlutterLogo(),
      ),
    );
  }
}
适用于可复用的动画组件:
dart
class AnimatedLogo extends AnimatedWidget {
  const AnimatedLogo({super.key, required Animation<double> animation})
    : super(listenable: animation);

  
  Widget build(BuildContext context) {
    final animation = listenable as Animation<double>;
    return Center(
      child: Container(
        height: animation.value,
        width: animation.value,
        child: const FlutterLogo(),
      ),
    );
  }
}

AnimatedBuilder Pattern

AnimatedBuilder 模式

Best for complex widgets with animations:
dart
class GrowTransition extends StatelessWidget {
  const GrowTransition({
    required this.child,
    required this.animation,
    super.key,
  });

  final Widget child;
  final Animation<double> animation;

  
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
        animation: animation,
        builder: (context, child) {
          return SizedBox(
            height: animation.value,
            width: animation.value,
            child: child,
          );
        },
        child: child,
      ),
    );
  }
}
适用于包含动画的复杂组件:
dart
class GrowTransition extends StatelessWidget {
  const GrowTransition({
    required this.child,
    required this.animation,
    super.key,
  });

  final Widget child;
  final Animation<double> animation;

  
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
        animation: animation,
        builder: (context, child) {
          return SizedBox(
            height: animation.value,
            width: animation.value,
            child: child,
          );
        },
        child: child,
      ),
    );
  }
}

Monitoring Animation State

监控动画状态

dart
animation.addStatusListener((status) {
  switch (status) {
    case AnimationStatus.completed:
      _controller.reverse();
      break;
    case AnimationStatus.dismissed:
      _controller.forward();
      break;
    default:
      break;
  }
});
dart
animation.addStatusListener((status) {
  switch (status) {
    case AnimationStatus.completed:
      _controller.reverse();
      break;
    case AnimationStatus.dismissed:
      _controller.forward();
      break;
    default:
      break;
  }
});

Multiple Simultaneous Animations

同时执行多个动画

dart
class AnimatedLogo extends AnimatedWidget {
  const AnimatedLogo({super.key, required Animation<double> animation})
    : super(listenable: animation);

  static final _opacityTween = Tween<double>(begin: 0.1, end: 1);
  static final _sizeTween = Tween<double>(begin: 0, end: 300);

  
  Widget build(BuildContext context) {
    final animation = listenable as Animation<double>;
    return Center(
      child: Opacity(
        opacity: _opacityTween.evaluate(animation),
        child: Container(
          height: _sizeTween.evaluate(animation),
          width: _sizeTween.evaluate(animation),
          child: const FlutterLogo(),
        ),
      ),
    );
  }
}
dart
class AnimatedLogo extends AnimatedWidget {
  const AnimatedLogo({super.key, required Animation<double> animation})
    : super(listenable: animation);

  static final _opacityTween = Tween<double>(begin: 0.1, end: 1);
  static final _sizeTween = Tween<double>(begin: 0, end: 300);

  
  Widget build(BuildContext context) {
    final animation = listenable as Animation<double>;
    return Center(
      child: Opacity(
        opacity: _opacityTween.evaluate(animation),
        child: Container(
          height: _sizeTween.evaluate(animation),
          width: _sizeTween.evaluate(animation),
          child: const FlutterLogo(),
        ),
      ),
    );
  }
}

Built-in Explicit Transitions

内置显式过渡组件

Flutter provides ready-to-use transitions:
  • FadeTransition
    - Fade animation
  • ScaleTransition
    - Scale animation
  • SlideTransition
    - Slide animation
  • SizeTransition
    - Size animation
  • RotationTransition
    - Rotation animation
  • PositionedTransition
    - Position animation (in Stack)
Example:
dart
FadeTransition(
  opacity: _animation,
  child: const FlutterLogo(),
)
Flutter提供了现成的过渡组件:
  • FadeTransition
    - 淡入淡出动画
  • ScaleTransition
    - 缩放动画
  • SlideTransition
    - 平移动画
  • SizeTransition
    - 尺寸动画
  • RotationTransition
    - 旋转动画
  • PositionedTransition
    - 位置动画(在Stack中使用)
示例:
dart
FadeTransition(
  opacity: _animation,
  child: const FlutterLogo(),
)

Performance Tips

性能优化技巧

  • Dispose controllers when widget is removed
  • Use
    AnimatedBuilder
    for optimal rebuilds
  • Avoid
    setState()
    in animation listeners (use
    AnimatedWidget
    /
    AnimatedBuilder
    )
  • Use
    timeDilation
    to slow animations during debugging
  • 组件移除时销毁控制器
  • 使用
    AnimatedBuilder
    实现最优重建
  • 避免在动画监听器中调用
    setState()
    (使用
    AnimatedWidget
    /
    AnimatedBuilder
  • 调试时使用
    timeDilation
    减慢动画速度

Hero Animations

Hero动画

Hero animations create shared element transitions between screens.
Hero动画实现页面间的共享元素过渡效果。

Basic Hero Animation

基础Hero动画

Source screen:
dart
Hero(
  tag: 'hero-image',
  child: Image.asset('images/logo.png'),
)
Destination screen:
dart
Hero(
  tag: 'hero-image',  // Same tag!
  child: Image.asset('images/logo.png'),
)
源页面:
dart
Hero(
  tag: 'hero-image',
  child: Image.asset('images/logo.png'),
)
目标页面:
dart
Hero(
  tag: 'hero-image',  // 标签必须相同!
  child: Image.asset('images/logo.png'),
)

Complete Example

完整示例

dart
class PhotoHero extends StatelessWidget {
  const PhotoHero({
    super.key,
    required this.photo,
    this.onTap,
    required this.width,
  });

  final String photo;
  final VoidCallback? onTap;
  final double width;

  
  Widget build(BuildContext context) {
    return SizedBox(
      width: width,
      child: Hero(
        tag: photo,
        child: Material(
          color: Colors.transparent,
          child: InkWell(
            onTap: onTap,
            child: Image.asset(photo, fit: BoxFit.contain),
          ),
        ),
      ),
    );
  }
}
Navigating between screens:
dart
Navigator.of(context).push(
  MaterialPageRoute<void>(
    builder: (context) {
      return Scaffold(
        appBar: AppBar(title: const Text('Detail')),
        body: Center(
          child: PhotoHero(
            photo: 'images/logo.png',
            width: 300.0,
            onTap: () => Navigator.of(context).pop(),
          ),
        ),
      );
    },
  ),
);
dart
class PhotoHero extends StatelessWidget {
  const PhotoHero({
    super.key,
    required this.photo,
    this.onTap,
    required this.width,
  });

  final String photo;
  final VoidCallback? onTap;
  final double width;

  
  Widget build(BuildContext context) {
    return SizedBox(
      width: width,
      child: Hero(
        tag: photo,
        child: Material(
          color: Colors.transparent,
          child: InkWell(
            onTap: onTap,
            child: Image.asset(photo, fit: BoxFit.contain),
          ),
        ),
      ),
    );
  }
}
页面导航:
dart
Navigator.of(context).push(
  MaterialPageRoute<void>(
    builder: (context) {
      return Scaffold(
        appBar: AppBar(title: const Text('详情页')),
        body: Center(
          child: PhotoHero(
            photo: 'images/logo.png',
            width: 300.0,
            onTap: () => Navigator.of(context).pop(),
          ),
        ),
      );
    },
  ),
);

Radial Hero Animation

径向Hero动画

Transform from circle to rectangle during transition:
dart
class RadialExpansion extends StatelessWidget {
  const RadialExpansion({
    super.key,
    required this.maxRadius,
    this.child,
  }) : clipRectSize = 2.0 * (maxRadius / math.sqrt2);

  final double maxRadius;
  final double clipRectSize;
  final Widget? child;

  
  Widget build(BuildContext context) {
    return ClipOval(
      child: Center(
        child: SizedBox(
          width: clipRectSize,
          height: clipRectSize,
          child: ClipRect(child: child),
        ),
      ),
    );
  }
}
Use with
MaterialRectCenterArcTween
for center-based interpolation:
dart
static RectTween _createRectTween(Rect? begin, Rect? end) {
  return MaterialRectCenterArcTween(begin: begin, end: end);
}
过渡过程中从圆形变换为矩形:
dart
class RadialExpansion extends StatelessWidget {
  const RadialExpansion({
    super.key,
    required this.maxRadius,
    this.child,
  }) : clipRectSize = 2.0 * (maxRadius / math.sqrt2);

  final double maxRadius;
  final double clipRectSize;
  final Widget? child;

  
  Widget build(BuildContext context) {
    return ClipOval(
      child: Center(
        child: SizedBox(
          width: clipRectSize,
          height: clipRectSize,
          child: ClipRect(child: child),
        ),
      ),
    );
  }
}
结合
MaterialRectCenterArcTween
实现基于中心的插值:
dart
static RectTween _createRectTween(Rect? begin, Rect? end) {
  return MaterialRectCenterArcTween(begin: begin, end: end);
}

Hero Best Practices

Hero动画最佳实践

  • Use unique, consistent tags (often the data object itself)
  • Keep hero widget trees similar between routes
  • Wrap images in
    Material
    with transparent color for "pop" effect
  • Use
    timeDilation
    to debug transitions
  • Consider
    HeroMode
    to disable hero animations when needed
  • 使用唯一且一致的标签(通常使用数据对象本身)
  • 保持页面间Hero组件树结构相似
  • 将图片包裹在透明颜色的
    Material
    组件中以实现返回效果
  • 使用
    timeDilation
    调试过渡效果
  • 必要时使用
    HeroMode
    禁用Hero动画

Staggered Animations

交错动画

Run multiple animations with different timing.
按不同时间执行多个动画。

Basic Staggered Animation

基础交错动画

All animations share one controller:
dart
class StaggerAnimation extends StatelessWidget {
  StaggerAnimation({super.key, required this.controller})
    : opacity = Tween<double>(begin: 0.0, end: 1.0).animate(
        CurvedAnimation(
          parent: controller,
          curve: const Interval(0.0, 0.100, curve: Curves.ease),
        ),
      ),
      width = Tween<double>(begin: 50.0, end: 150.0).animate(
        CurvedAnimation(
          parent: controller,
          curve: const Interval(0.125, 0.250, curve: Curves.ease),
        ),
      );

  final AnimationController controller;
  final Animation<double> opacity;
  final Animation<double> width;

  Widget _buildAnimation(BuildContext context, Widget? child) {
    return Container(
      alignment: Alignment.bottomCenter,
      child: Opacity(
        opacity: opacity.value,
        child: Container(
          width: width.value,
          height: 150,
          color: Colors.blue,
        ),
      ),
    );
  }

  
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: controller,
      builder: _buildAnimation,
    );
  }
}
所有动画共享同一个控制器:
dart
class StaggerAnimation extends StatelessWidget {
  StaggerAnimation({super.key, required this.controller})
    : opacity = Tween<double>(begin: 0.0, end: 1.0).animate(
        CurvedAnimation(
          parent: controller,
          curve: const Interval(0.0, 0.100, curve: Curves.ease),
        ),
      ),
      width = Tween<double>(begin: 50.0, end: 150.0).animate(
        CurvedAnimation(
          parent: controller,
          curve: const Interval(0.125, 0.250, curve: Curves.ease),
        ),
      );

  final AnimationController controller;
  final Animation<double> opacity;
  final Animation<double> width;

  Widget _buildAnimation(BuildContext context, Widget? child) {
    return Container(
      alignment: Alignment.bottomCenter,
      child: Opacity(
        opacity: opacity.value,
        child: Container(
          width: width.value,
          height: 150,
          color: Colors.blue,
        ),
      ),
    );
  }

  
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: controller,
      builder: _buildAnimation,
    );
  }
}

Interval-Based Timing

基于时间间隔的时序控制

Each animation has an Interval between 0.0 and 1.0:
dart
animation = Tween<double>(begin: 0, end: 300).animate(
  CurvedAnimation(
    parent: controller,
    curve: const Interval(
      0.25,  // Start at 25% of controller duration
      0.50,  // End at 50% of controller duration
      curve: Curves.ease,
    ),
  ),
);
每个动画在0.0到1.0之间有一个时间间隔:
dart
animation = Tween<double>(begin: 0, end: 300).animate(
  CurvedAnimation(
    parent: controller,
    curve: const Interval(
      0.25,  // 在控制器时长的25%处开始
      0.50,  // 在控制器时长的50%处结束
      curve: Curves.ease,
    ),
  ),
);

Common Tweens

常用补间动画

dart
borderRadius = BorderRadiusTween(
  begin: BorderRadius.circular(4),
  end: BorderRadius.circular(75),
).animate(
  CurvedAnimation(
    parent: controller,
    curve: const Interval(0.375, 0.500, curve: Curves.ease),
  ),
);
dart
borderRadius = BorderRadiusTween(
  begin: BorderRadius.circular(4),
  end: BorderRadius.circular(75),
).animate(
  CurvedAnimation(
    parent: controller,
    curve: const Interval(0.375, 0.500, curve: Curves.ease),
  ),
);

Staggered Menu Animation

交错菜单动画

dart
class _MenuState extends State<Menu> with SingleTickerProviderStateMixin {
  static const _initialDelayTime = Duration(milliseconds: 50);
  static const _itemSlideTime = Duration(milliseconds: 250);
  static const _staggerTime = Duration(milliseconds: 50);
  static const _buttonDelayTime = Duration(milliseconds: 150);
  static const _buttonTime = Duration(milliseconds: 500);

  final _animationDuration =
      _initialDelayTime +
      (_staggerTime * _menuTitles.length) +
      _buttonDelayTime +
      _buttonTime;

  late AnimationController _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: _animationDuration,
      vsync: this,
    );
    _controller.forward();
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
dart
class _MenuState extends State<Menu> with SingleTickerProviderStateMixin {
  static const _initialDelayTime = Duration(milliseconds: 50);
  static const _itemSlideTime = Duration(milliseconds: 250);
  static const _staggerTime = Duration(milliseconds: 50);
  static const _buttonDelayTime = Duration(milliseconds: 150);
  static const _buttonTime = Duration(milliseconds: 500);

  final _animationDuration =
      _initialDelayTime +
      (_staggerTime * _menuTitles.length) +
      _buttonDelayTime +
      _buttonTime;

  late AnimationController _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: _animationDuration,
      vsync: this,
    );
    _controller.forward();
  }

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

Stagger Best Practices

交错动画最佳实践

  • Use
    Interval
    to offset animations in time
  • Ensure controller duration covers all intervals
  • Use curves for natural motion within intervals
  • Consider
    timeDilation
    to debug timing
  • Stagger menu items with increasing delay for ripple effect
  • 使用
    Interval
    来偏移动画的执行时间
  • 确保控制器时长覆盖所有时间间隔
  • 在时间间隔内使用曲线实现自然动效
  • 调试时序时使用
    timeDilation
  • 为菜单项设置递增的延迟时间以实现涟漪效果

Physics-Based Animations

基于物理的动画

Create natural-feeling animations using physics simulations.
使用物理模拟创建自然的动画效果。

Fling Animation

抛掷动画

dart
_controller.fling(
  velocity: 2.0,  // Units per second
);
dart
_controller.fling(
  velocity: 2.0,  // 单位:每秒
);

Custom Physics Simulation

自定义物理模拟

dart
_controller.animateWith(
  SpringSimulation(
    spring: const SpringDescription(
      mass: 1,
      stiffness: 100,
      damping: 10,
    ),
    start: 0.0,
    end: 1.0,
    velocity: 0.0,
  ),
);
dart
_controller.animateWith(
  SpringSimulation(
    spring: const SpringDescription(
      mass: 1,
      stiffness: 100,
      damping: 10,
    ),
    start: 0.0,
    end: 1.0,
    velocity: 0.0,
  ),
);

Common Physics Simulations

常用物理模拟

  • SpringSimulation
    - Spring physics
  • BouncingScrollSimulation
    - Scroll with bounce
  • ClampingScrollSimulation
    - Scroll without bounce
  • GravitySimulation
    - Gravity-based
  • SpringSimulation
    - 弹簧物理效果
  • BouncingScrollSimulation
    - 带回弹的滚动效果
  • ClampingScrollSimulation
    - 无回弹的滚动效果
  • GravitySimulation
    - 基于重力的效果

Best Practices

最佳实践

DO

建议

  • Dispose AnimationController in widget disposal
  • Use
    AnimatedBuilder
    /
    AnimatedWidget
    instead of
    setState()
    in listeners
  • Choose appropriate curves for natural motion
  • Use
    timeDilation
    for debugging animations
  • Consider performance (avoid heavy widgets in animation builds)
  • Test animations on various devices
  • Support reverse animations for intuitive feel
  • 在组件销毁时释放AnimationController
  • 使用
    AnimatedBuilder
    /
    AnimatedWidget
    替代监听器中的
    setState()
  • 选择合适的曲线实现自然动效
  • 使用
    timeDilation
    调试动画
  • 考虑性能(避免在动画构建中使用重型组件)
  • 在不同设备上测试动画
  • 支持反向动画以提升直观性

DON'T

禁忌

  • Forget to dispose AnimationController (memory leak)
  • Use
    setState()
    in animation listeners when
    AnimatedBuilder
    suffices
  • Assume animation completes instantly (handle
    AnimationStatus
    )
  • Over-animate (animations can distract users)
  • Create animations that feel "jerky" (use smooth curves)
  • Ignore accessibility (respect
    disableAnimations
    preference)
  • 忘记释放AnimationController(会导致内存泄漏)
  • AnimatedBuilder
    足够时,仍在动画监听器中使用
    setState()
  • 假设动画会立即完成(处理
    AnimationStatus
  • 过度使用动画(动画可能会分散用户注意力)
  • 创建“卡顿”的动画(使用平滑曲线)
  • 忽略可访问性(尊重
    disableAnimations
    偏好设置)

Resources

资源

references/

references/

implicit.md - Complete reference for implicit animation widgets with examples and best practices.
explicit.md - Deep dive into explicit animations, AnimationController, and patterns.
hero.md - Hero animations guide with standard and radial transitions.
staggered.md - Staggered animation patterns and timing strategies.
physics.md - Physics-based animations and simulations.
curves.md - Reference for Curves class and choosing appropriate curves.
implicit.md - 隐式动画组件的完整参考,包含示例和最佳实践。
explicit.md - 深入讲解显式动画、AnimationController及相关模式。
hero.md - Hero动画指南,包含标准和径向过渡效果。
staggered.md - 交错动画模式和时序策略。
physics.md - 基于物理的动画和模拟。
curves.md - Curves类参考及曲线选择指南。

assets/templates/

assets/templates/

Template code for common animation patterns:
  • implicit_animation.dart
    - Implicit animation examples
  • explicit_animation.dart
    - Explicit animation setup
  • hero_transition.dart
    - Hero animation boilerplate
  • staggered_animation.dart
    - Staggered animation template
常见动画模式的模板代码:
  • implicit_animation.dart
    - 隐式动画示例
  • explicit_animation.dart
    - 显式动画设置模板
  • hero_transition.dart
    - Hero动画样板代码
  • staggered_animation.dart
    - 交错动画模板