当前位置: 首页 > news >正文

Flutter AnimationController:掌握动画的节奏

Flutter AnimationController:掌握动画的节奏

从基础到高级,掌握 Flutter 动画控制器的全部潜能。

一、AnimationController 的核心价值

作为一名追求像素级还原的 UI 匠人,我对动画有着特殊的情感。AnimationController 是 Flutter 动画系统的核心,它就像是动画的指挥家,控制着动画的开始、暂停、反向和速度。掌握它,你就能创造出流畅、自然的动画效果。

二、基础用法

1. 基本设置

import 'package:flutter/material.dart'; class BasicAnimation extends StatefulWidget { @override _BasicAnimationState createState() => _BasicAnimationState(); } class _BasicAnimationState extends State<BasicAnimation> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(seconds: 2), vsync: this, ); _animation = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); _controller.forward(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('基础动画')), body: Center( child: AnimatedBuilder( animation: _animation, builder: (context, child) { return Transform.scale( scale: _animation.value, child: Container( width: 200, height: 200, decoration: BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF667eea), Color(0xFF764ba2)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), ), ), ); }, ), ), floatingActionButton: FloatingActionButton( onPressed: () { if (_controller.isCompleted) { _controller.reverse(); } else { _controller.forward(); } }, child: Icon(Icons.play_arrow), ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } }

2. 动画曲线

class CurvedAnimationExample extends StatefulWidget { @override _CurvedAnimationExampleState createState() => _CurvedAnimationExampleState(); } class _CurvedAnimationExampleState extends State<CurvedAnimationExample> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(seconds: 3), vsync: this, ); // 使用不同的曲线 _animation = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation( parent: _controller, curve: Curves.bounceOut, ), ); _controller.repeat(reverse: true); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('动画曲线')), body: Center( child: AnimatedBuilder( animation: _animation, builder: (context, child) { return Transform.translate( offset: Offset(0, _animation.value * 200 - 100), child: Container( width: 100, height: 100, decoration: BoxDecoration( color: Color(0xFF667eea), borderRadius: BorderRadius.circular(50), ), ), ); }, ), ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } }

三、高级用法

1. 多动画协调

class MultipleAnimations extends StatefulWidget { @override _MultipleAnimationsState createState() => _MultipleAnimationsState(); } class _MultipleAnimationsState extends State<MultipleAnimations> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _scaleAnimation; late Animation<double> _opacityAnimation; late Animation<Offset> _positionAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(seconds: 2), vsync: this, ); _scaleAnimation = Tween<double>(begin: 0.5, end: 1.0).animate( CurvedAnimation(parent: _controller, curve: Curves.easeOut), ); _opacityAnimation = Tween<double>(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _controller, curve: Curves.easeIn), ); _positionAnimation = Tween<Offset>( begin: Offset(0, -50), end: Offset(0, 0), ).animate( CurvedAnimation(parent: _controller, curve: Curves.bounceOut), ); _controller.forward(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('多动画协调')), body: Center( child: AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.translate( offset: _positionAnimation.value, child: Opacity( opacity: _opacityAnimation.value, child: Transform.scale( scale: _scaleAnimation.value, child: Container( width: 200, height: 200, decoration: BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF667eea), Color(0xFF764ba2)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), ), child: Center( child: Text( '动画组合', style: TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), ), ), ), ), ); }, ), ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } }

2. 动画序列

class AnimationSequence extends StatefulWidget { @override _AnimationSequenceState createState() => _AnimationSequenceState(); } class _AnimationSequenceState extends State<AnimationSequence> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _firstAnimation; late Animation<double> _secondAnimation; late Animation<double> _thirdAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(seconds: 4), vsync: this, ); // 第一个动画:0-1秒 _firstAnimation = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation( parent: _controller, curve: Interval(0.0, 0.25, curve: Curves.easeOut), ), ); // 第二个动画:1-2秒 _secondAnimation = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation( parent: _controller, curve: Interval(0.25, 0.5, curve: Curves.easeOut), ), ); // 第三个动画:2-4秒 _thirdAnimation = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation( parent: _controller, curve: Interval(0.5, 1.0, curve: Curves.easeOut), ), ); _controller.forward(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('动画序列')), body: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ AnimatedBuilder( animation: _firstAnimation, builder: (context, child) { return Transform.scale( scale: _firstAnimation.value, child: Container( width: 100, height: 100, color: Color(0xFF667eea), ), ); }, ), AnimatedBuilder( animation: _secondAnimation, builder: (context, child) { return Transform.scale( scale: _secondAnimation.value, child: Container( width: 100, height: 100, color: Color(0xFF764ba2), ), ); }, ), AnimatedBuilder( animation: _thirdAnimation, builder: (context, child) { return Transform.scale( scale: _thirdAnimation.value, child: Container( width: 100, height: 100, color: Color(0xFFf093fb), ), ); }, ), ], ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } }

3. 物理动画

class PhysicsAnimation extends StatefulWidget { @override _PhysicsAnimationState createState() => _PhysicsAnimationState(); } class _PhysicsAnimationState extends State<PhysicsAnimation> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<Offset> _animation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, ); // 物理弹簧动画 final spring = SpringSimulation( SpringDescription( mass: 1.0, stiffness: 100.0, damping: 10.0, ), 0.0, 1.0, 0.0, ); _animation = _controller.drive( Tween<Offset>( begin: Offset(-1, 0), end: Offset(0, 0), ), ); _controller.animateWith(spring); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('物理动画')), body: Center( child: SlideTransition( position: _animation, child: Container( width: 200, height: 200, decoration: BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF667eea), Color(0xFF764ba2)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), ), ), ), ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } }

四、性能优化

  1. 使用 const 构造器:减少不必要的重建
  2. 合理使用 AnimatedBuilder:只重建需要动画的部分
  3. 避免在动画回调中做耗时操作:保持动画流畅
  4. 使用 RepaintBoundary:隔离重绘区域

五、最佳实践

  1. 始终 dispose:在 State 中使用 AnimationController 时,一定要在 dispose 方法中释放
  2. 使用 vsync:避免不必要的动画刷新
  3. 合理设置 duration:根据动画类型设置合适的时长
  4. 测试性能:在低端设备上测试动画流畅度

动画是界面的灵魂,AnimationController 是灵魂的指挥家。

#flutter #animation #animation-controller #dart #ui

http://www.jsqmd.com/news/603708/

相关文章:

  • 2026适合在家染的盖白染发膏实用指南 - 品牌排行榜
  • 【PythonAI】2.2.2 技能实训:使用Pandas读取CSV/Excel文件,查看数据概览(2. 数据质量评估)
  • OpenClaw+千问3.5-9B邮件处理:自动分类与智能回复草稿
  • 2026医考十大机构综合实力榜发布:四大核心维度权威评测 - 医考机构品牌测评专家
  • 口碑封神!2026年值得信赖的GEO优化公司盘点,企业避坑必看 - 品牌测评鉴赏家
  • Vue.js监听器watch利用回调函数处理级联下拉框数据联动
  • 【JPCS出版,录用率高,快至提交出版后1个月见刊 | 高届数,EI检索有保障 | 多位院士杰青领衔报告 | 设置评优评奖环节】第十三届先进制造技术与材料工程国际学术会议 (AMTME 2026)
  • RNN、LSTM、BiLSTM学习笔记
  • 飞檐走壁分科目比赛建议
  • 【Motrix】Motrix官网下载:中文版下载工具使用指南(2026实测) - xiema
  • 读懂公司第二篇-利润表深度解读 - 智慧园区
  • 实战指南:基于快马生成的配置将openclaw部署至生产环境
  • SAP权限对象深度解析:如何用SU21自定义企业级数据权限控制?
  • 电机控制-MOS驱动和MOSFET如何匹配的,并计算栅极驱动电阻
  • 从手动到半自动:详解Metashape控制点校准航拍影像偏移的实战流程
  • MMsegmentation训练卡在第一个epoch?手把手教你修改DefaultSampler和EpochBasedRunner
  • 必看!2026主流GEO服务商盘点,新手博主/商家避坑指南 - 品牌测评鉴赏家
  • 别再问哪个AI 最强了,把它们放进同一个考场就知道
  • 解锁3大网页设计黑科技:从像素到原型的无缝转换
  • C++的std--ranges适配器元素
  • 2026上班族白发用什么染发膏好?温和便捷成首选 - 品牌排行榜
  • AI初创公司Rocket推出低成本咨询级产品策略报告平台
  • Go Module 的依赖版本控制
  • 2026防脱精华液适合男士的品牌推荐及养护指南 - 品牌排行榜
  • 测试工程师的悲哀:我们正在成为“人肉脚本”
  • 新概念英语第一册103_The French test
  • HTML打包EXE配置管理教程:多项目打包设置一键保存、加载与切换
  • 企业 AI 看起来很热,为什么真正稳定见效的并不多
  • Java 设计模式最佳实践:构建可维护的应用
  • LongCat-Image-Editn参数详解:UNet结构精简设计+CLIP文本编码器微调策略