Flutter动画详解与实战什么是Flutter动画Flutter提供了强大的动画系统允许我们创建流畅、美观的用户界面。动画在Flutter中是通过Animation、AnimationController、Tween等类来实现的它们共同构成了Flutter的动画框架。动画基础1. Animation和AnimationControllerAnimation是Flutter动画的核心类它表示动画的当前状态和值。AnimationController用于控制动画的播放、暂停、反转等操作。import package:flutter/material.dart; class MyAnimation extends StatefulWidget { override _MyAnimationState createState() _MyAnimationState(); } class _MyAnimationState extends StateMyAnimation with SingleTickerProviderStateMixin { late AnimationController _controller; late Animationdouble _animation; override void initState() { super.initState(); // 创建AnimationController设置动画时长为2秒 _controller AnimationController( duration: Duration(seconds: 2), vsync: this, ); // 创建动画从0.0到1.0 _animation Tweendouble(begin: 0.0, end: 1.0).animate(_controller); // 启动动画 _controller.forward(); } override void dispose() { _controller.dispose(); super.dispose(); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(Flutter动画示例), ), body: Center( child: AnimatedBuilder( animation: _animation, builder: (context, child) { return Container( width: _animation.value * 200, height: _animation.value * 200, color: Colors.blue, ); }, ), ), ); } }2. TweenTween用于定义动画的起始值和结束值。// 创建一个从0.0到1.0的动画 Animationdouble animation Tweendouble(begin: 0.0, end: 1.0).animate(controller); // 创建一个颜色渐变动画 AnimationColor colorAnimation ColorTween( begin: Colors.red, end: Colors.blue, ).animate(controller); // 创建一个大小渐变动画 AnimationSize sizeAnimation SizeTween( begin: Size(100, 100), end: Size(200, 200), ).animate(controller);3. CurvedAnimationCurvedAnimation用于添加动画曲线使动画更加自然。Animationdouble animation CurvedAnimation( parent: controller, curve: Curves.easeInOut, ); // 常用的动画曲线 // Curves.linear - 线性 // Curves.ease - 缓入缓出 // Curves.easeIn - 缓入 // Curves.easeOut - 缓出 // Curves.easeInOut - 缓入缓出 // Curves.bounceIn - 弹跳进入 // Curves.bounceOut - 弹跳退出 // Curves.elasticIn - 弹性进入 // Curves.elasticOut - 弹性退出 // Curves.elasticInOut - 弹性进入退出动画类型1. 显式动画显式动画是通过AnimationController和Tween手动控制的动画。class FadeTransitionExample extends StatefulWidget { override _FadeTransitionExampleState createState() _FadeTransitionExampleState(); } class _FadeTransitionExampleState extends StateFadeTransitionExample with SingleTickerProviderStateMixin { late AnimationController _controller; late Animationdouble _opacityAnimation; override void initState() { super.initState(); _controller AnimationController( duration: Duration(seconds: 2), vsync: this, ); _opacityAnimation Tweendouble(begin: 0.0, end: 1.0).animate(_controller); _controller.repeat(reverse: true); } override void dispose() { _controller.dispose(); super.dispose(); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(淡入淡出动画), ), body: Center( child: FadeTransition( opacity: _opacityAnimation, child: Container( width: 200, height: 200, color: Colors.blue, ), ), ), ); } }2. 隐式动画隐式动画是Flutter提供的简化动画实现通过AnimatedContainer、AnimatedOpacity等组件实现。class ImplicitAnimationExample extends StatefulWidget { override _ImplicitAnimationExampleState createState() _ImplicitAnimationExampleState(); } class _ImplicitAnimationExampleState extends StateImplicitAnimationExample { bool _isExpanded false; override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(隐式动画示例), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ AnimatedContainer( duration: Duration(seconds: 1), width: _isExpanded ? 300 : 100, height: _isExpanded ? 300 : 100, color: _isExpanded ? Colors.red : Colors.blue, curve: Curves.easeInOut, ), SizedBox(height: 20), ElevatedButton( onPressed: () { setState(() { _isExpanded !_isExpanded; }); }, child: Text(_isExpanded ? 收缩 : 展开), ), ], ), ), ); } }3. 物理动画物理动画是基于物理规律的动画通过PhysicsSimulation实现。class PhysicsAnimationExample extends StatefulWidget { override _PhysicsAnimationExampleState createState() _PhysicsAnimationExampleState(); } class _PhysicsAnimationExampleState extends StatePhysicsAnimationExample with SingleTickerProviderStateMixin { late AnimationController _controller; late Animationdouble _animation; override void initState() { super.initState(); _controller AnimationController( duration: Duration(seconds: 2), vsync: this, ); // 创建一个弹簧动画 _animation _controller.drive( Tweendouble(begin: 0.0, end: 1.0).chain( CurveTween(curve: Curves.elasticOut), ), ); _controller.forward(); } override void dispose() { _controller.dispose(); super.dispose(); } 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, color: Colors.blue, ), ); }, ), ), ); } }动画组件1. AnimatedBuilderAnimatedBuilder是一个通用的动画构建器用于构建自定义动画。AnimatedBuilder( animation: _animation, builder: (context, child) { return Transform.rotate( angle: _animation.value * 2 * math.pi, child: child, ); }, child: Container( width: 200, height: 200, color: Colors.blue, ), )2. FadeTransitionFadeTransition用于实现淡入淡出动画。FadeTransition( opacity: _animation, child: Container( width: 200, height: 200, color: Colors.blue, ), )3. ScaleTransitionScaleTransition用于实现缩放动画。ScaleTransition( scale: _animation, child: Container( width: 200, height: 200, color: Colors.blue, ), )4. RotationTransitionRotationTransition用于实现旋转动画。RotationTransition( turns: _animation, child: Container( width: 200, height: 200, color: Colors.blue, ), )5. SlideTransitionSlideTransition用于实现平移动画。SlideTransition( position: TweenOffset( begin: Offset(-1.0, 0.0), end: Offset(0.0, 0.0), ).animate(_animation), child: Container( width: 200, height: 200, color: Colors.blue, ), )6. AnimatedContainerAnimatedContainer用于实现容器属性的动画变化。AnimatedContainer( duration: Duration(seconds: 1), width: _width, height: _height, color: _color, curve: Curves.easeInOut, )7. AnimatedOpacityAnimatedOpacity用于实现透明度的动画变化。AnimatedOpacity( duration: Duration(seconds: 1), opacity: _opacity, child: Container( width: 200, height: 200, color: Colors.blue, ), )8. AnimatedPositionedAnimatedPositioned用于实现Stack中组件位置的动画变化。Stack( children: [ AnimatedPositioned( duration: Duration(seconds: 1), left: _left, top: _top, child: Container( width: 100, height: 100, color: Colors.blue, ), ), ], )动画实战1. 按钮点击动画class ButtonAnimation extends StatefulWidget { override _ButtonAnimationState createState() _ButtonAnimationState(); } class _ButtonAnimationState extends StateButtonAnimation with SingleTickerProviderStateMixin { late AnimationController _controller; late Animationdouble _scaleAnimation; bool _isPressed false; override void initState() { super.initState(); _controller AnimationController( duration: Duration(milliseconds: 200), vsync: this, ); _scaleAnimation Tweendouble(begin: 1.0, end: 0.9).animate(_controller); } override void dispose() { _controller.dispose(); super.dispose(); } void _onTapDown(TapDownDetails details) { _controller.forward(); setState(() { _isPressed true; }); } void _onTapUp(TapUpDetails details) { _controller.reverse(); setState(() { _isPressed false; }); } void _onTapCancel() { _controller.reverse(); setState(() { _isPressed false; }); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(按钮点击动画), ), body: Center( child: GestureDetector( onTapDown: _onTapDown, onTapUp: _onTapUp, onTapCancel: _onTapCancel, child: ScaleTransition( scale: _scaleAnimation, child: Container( padding: EdgeInsets.symmetric(horizontal: 30, vertical: 15), decoration: BoxDecoration( color: _isPressed ? Colors.blue[700] : Colors.blue, borderRadius: BorderRadius.circular(8), ), child: Text( 点击我, style: TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), ), ), ), ), ); } }2. 加载动画class LoadingAnimation extends StatefulWidget { override _LoadingAnimationState createState() _LoadingAnimationState(); } class _LoadingAnimationState extends StateLoadingAnimation with SingleTickerProviderStateMixin { late AnimationController _controller; late Animationdouble _rotationAnimation; override void initState() { super.initState(); _controller AnimationController( duration: Duration(seconds: 1), vsync: this, )..repeat(); _rotationAnimation Tweendouble(begin: 0.0, end: 1.0).animate(_controller); } override void dispose() { _controller.dispose(); super.dispose(); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(加载动画), ), body: Center( child: RotationTransition( turns: _rotationAnimation, child: Container( width: 50, height: 50, decoration: BoxDecoration( border: Border.all(color: Colors.blue, width: 4), borderTopColor: Colors.transparent, borderRadius: BorderRadius.circular(25), ), ), ), ), ); } }3. 页面过渡动画class PageTransitionAnimation extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(页面过渡动画), ), body: Center( child: ElevatedButton( onPressed: () { Navigator.push( context, PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) SecondPage(), transitionsBuilder: (context, animation, secondaryAnimation, child) { const begin Offset(1.0, 0.0); const end Offset.zero; const curve Curves.ease; var tween Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); return SlideTransition( position: animation.drive(tween), child: child, ); }, ), ); }, child: Text(跳转到第二页), ), ), ); } } class SecondPage extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(第二页), ), body: Center( child: ElevatedButton( onPressed: () { Navigator.pop(context); }, child: Text(返回第一页), ), ), ); } }4. 列表项动画class ListItemAnimation extends StatefulWidget { override _ListItemAnimationState createState() _ListItemAnimationState(); } class _ListItemAnimationState extends StateListItemAnimation with SingleTickerProviderStateMixin { late AnimationController _controller; ListAnimationdouble _animations []; ListString _items [项目1, 项目2, 项目3, 项目4, 项目5]; override void initState() { super.initState(); _controller AnimationController( duration: Duration(seconds: 1), vsync: this, ); _animations List.generate( _items.length, (index) Tweendouble(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: Interval(index * 0.1, 1.0, curve: Curves.easeOut), ), ), ); _controller.forward(); } override void dispose() { _controller.dispose(); super.dispose(); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(列表项动画), ), body: ListView.builder( itemCount: _items.length, itemBuilder: (context, index) { return FadeTransition( opacity: _animations[index], child: SlideTransition( position: TweenOffset( begin: Offset(0.0, 0.5), end: Offset(0.0, 0.0), ).animate(_animations[index]), child: ListTile( title: Text(_items[index]), leading: Icon(Icons.list), ), ), ); }, ), ); } }5. 复杂动画组合class ComplexAnimation extends StatefulWidget { override _ComplexAnimationState createState() _ComplexAnimationState(); } class _ComplexAnimationState extends StateComplexAnimation with SingleTickerProviderStateMixin { late AnimationController _controller; late Animationdouble _scaleAnimation; late Animationdouble _rotationAnimation; late AnimationColor _colorAnimation; override void initState() { super.initState(); _controller AnimationController( duration: Duration(seconds: 2), vsync: this, )..repeat(reverse: true); _scaleAnimation Tweendouble(begin: 1.0, end: 1.2).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); _rotationAnimation Tweendouble(begin: 0.0, end: 0.1).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); _colorAnimation ColorTween( begin: Colors.blue, end: Colors.red, ).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); } override void dispose() { _controller.dispose(); super.dispose(); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(复杂动画组合), ), body: Center( child: AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.scale( scale: _scaleAnimation.value, child: Transform.rotate( angle: _rotationAnimation.value, child: Container( width: 200, height: 200, color: _colorAnimation.value, child: Center( child: Text( 动画示例, style: TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), ), ), ), ), ); }, ), ), ); } }动画性能优化使用const构造函数对于不需要重建的组件使用const构造函数使用RepaintBoundary对于复杂动画使用RepaintBoundary避免不必要的重建使用AnimatedBuilder使用AnimatedBuilder可以避免整个组件的重建控制动画帧率对于复杂动画可以降低动画帧率使用shouldRepaint对于自定义Painter实现shouldRepaint方法动画最佳实践保持动画简洁避免过于复杂的动画保持动画简洁明了使用合适的动画曲线根据场景选择合适的动画曲线控制动画时长动画时长应该适中不宜过长或过短考虑用户体验动画应该增强用户体验而不是干扰用户测试不同设备在不同设备上测试动画确保流畅运行常见问题与解决方案1. 动画不流畅原因动画过于复杂或设备性能不足解决方案优化动画使用RepaintBoundary降低动画复杂度2. 动画重复播放原因AnimationController没有正确dispose解决方案在dispose方法中调用_controller.dispose()3. 动画不同步原因多个动画使用不同的AnimationController解决方案使用同一个AnimationController控制多个动画4. 动画内存泄漏原因AnimationController没有正确dispose解决方案在dispose方法中调用_controller.dispose()总结Flutter提供了强大的动画系统支持各种类型的动画包括显式动画、隐式动画和物理动画。通过掌握动画的基本概念和组件我们可以创建出流畅、美观的用户界面。在使用动画时我们应该注意性能优化确保动画在各种设备上都能流畅运行。同时我们应该根据场景选择合适的动画类型和曲线以增强用户体验。希望本文对你理解和应用Flutter动画有所帮助