Flutter 动画组件详解Flutter 提供了丰富的动画组件,可以分为两大类:隐式动画(自动动画)和显式动画(手动控制动画)。隐式动画组件隐式动画组件会自动处理动画过渡,只需提供目标值即可。1.AnimatedContainer - 容器动画classAnimatedContainerExampleextendsStatefulWidget{@override_AnimatedContainerExampleStatecreateState()=_AnimatedContainerExampleState();}class_AnimatedContainerExampleStateextendsStateAnimatedContainerExample{bool _isExpanded=false;@overrideWidgetbuild(BuildContextcontext){returnGestureDetector(onTap:(){setState((){_isExpanded=!_isExpanded;});},child:AnimatedContainer(duration:Duration(milliseconds:300),// 动画持续时间curve:Curves.easeInOut,// 动画曲线width:_isExpanded?200:100,// 宽度变化height:_isExpanded?200:100,// 高度变化color:_isExpanded?Colors.red:Colors.blue,// 颜色变化alignment:_isExpanded?Alignment.center:Alignment.topLeft,// 对齐方式变化child:Text(_isExpanded?'展开':'收缩',style:TextStyle(color:Colors.white,fontSize:16,),),),);}}2.AnimatedOpacity - 透明度动画classAnimatedOpacityExampleextendsStatefulWidget{@override_AnimatedOpacityExampleStatecreateState()=_AnimatedOpacityExampleState();}class_AnimatedOpacityExampleStateextendsStateAnimatedOpacityExample{bool _isVisible=true;@overrideWidgetbuild(BuildContextcontext){returnGestureDetector(onTap:(){setState((){_isVisible=!_isVisible;});},child:AnimatedOpacity(duration:Duration(milliseconds:300),opacity:_isVisible?1.0:0.0,// 透明度变化child:Container(width:100,height:100,color:Colors.blue,child:Center(child:Text(_isVisible?'可见':'隐藏',style:TextStyle(color:Colors.white,fontSize:16,),),),),),);}}3.AnimatedPadding - 内边距动画classAnimatedPaddingExampleextendsStatefulWidget{@override_AnimatedPaddingExampleStatecreateState()=_AnimatedPaddingExampleState();}class_AnimatedPaddingExampleStateextendsStateAnimatedPaddingExample{bool _isPadded=false;@overrideWidgetbuild(BuildContextcontext){returnGestureDetector(onTap:(){setState((){_isPadded=!_isPadded;});},child:AnimatedPadding(duration:Duration(milliseconds:300),padding:_isPadded?EdgeInsets.all(20):EdgeInsets.all(0),// 内边距变化child:Container(width:100,height:100,color:Colors.blue,child:Center(child:Text(_isPadded?'有内边距':'无内边距',style:TextStyle(color:Colors.white,fontSize:16,),),),),),);}}4.AnimatedPositioned - 位置动画classAnimatedPositionedExampleextendsStatefulWidget{@override_AnimatedPositionedExampleStatecreateState()=_AnimatedPositionedExampleState();}class_AnimatedPositionedExampleStateextendsStateAnimatedPositionedExample{bool _isMoved=false;@overrideWidgetbuild(BuildContextcontext){returnContainer(width:200,height:200,color:Colors.grey,child:Stack(children:[AnimatedPositioned(duration:Duration(milliseconds:300),left:_isMoved?100:0,// 左侧位置变化top:_isMoved?100:0,// 顶部位置变化child:Container(width:50,height:50,color:Colors.red,child:Center(child:Text(_isMoved?'移动后':'移动前',style:TextStyle(color:Colors.white,fontSize:12,),),),),),GestureDetector(onTap:(){setState((){_isMoved=!_isMoved;});},child:Container(width:200,height:200,color:Colors.transparent,),),],),);}}5.AnimatedAlign - 对齐动画classAnimatedAlignExampleextendsStatefulWidget{@override_AnimatedAlignExampleStatecreateState()=_AnimatedAlignExampleState();}class_AnimatedAlignExampleStateextendsStateAnimatedAlignExample{Alignment_alignment=Alignment.topLeft;@overrideWidgetbuild(BuildContextcontext){returnGestureDetector(onTap:(){setState((){_alignment=_alignment==Alignment.topLeft?Alignment.bottomRight:Alignment.topLeft;});},child:Container(width:200,height:200,color:Colors.grey,child:AnimatedAlign(duration:Duration(milliseconds:300),alignment:_alignment,// 对齐方式变化child:Container(width:50,height:50,color:Colors.red,child:Center(child:Text(_alignment==Alignment.topLeft?'左上':'右下',style:TextStyle(color:Colors.white,fontSize:12,),),),),),),);}}6.AnimatedCrossFade - 交叉淡入淡出动画classAnimatedCrossFadeExampleextendsStatefulWidget{@override_AnimatedCrossFadeExampleStatecreateState()=_AnimatedCrossFadeExampleState();}class_AnimatedCrossFadeExampleStateextendsStateAnimatedCrossFadeExample{bool _showFirst=true;@overrideWidgetbuild(BuildContextcontext){returnGestureDetector(onTap:(){setState((){_showFirst=!_showFirst;});},child:AnimatedCrossFade(duration:Duration(milliseconds:300),crossFadeState:_showFirst?CrossFadeState.showFirst:CrossFadeState.showSecond,// 显示状态变化firstChild:Container(width:100,height:100,color:Colors.red,child:Center(child:Text('第一个',style:TextStyle(color:Colors.white,fontSize:16,),),),),secondChild:Container(width:100,height:100,color:Colors.blue,child:Center(child:Text('第二个',style:TextStyle(color:Colors.white,fontSize:16,),),),),),);}}7.AnimatedSize - 尺寸动画classAnimatedSizeExampleextendsStatefulWidget{@override_AnimatedSizeExampleStatecreateState()=_AnimatedSizeExampleState();}class_AnimatedSizeExampleStateextendsStateAnimatedSizeExample{bool _isExpanded=false;@overrideWidgetbuild(BuildContextcontext){returnGestureDetector(onTap:(){setState((){_isExpanded=!_isExpanded;});},child:AnimatedSize(duration:Duration(milliseconds:300),child:Container(width:_isExpanded?200:100,height:_isExpanded?200:100,color:Colors.blue,child:Center(child:Text(_isExpanded?'展开':'收缩',style:TextStyle(color:Colors.white,fontSize:16,),),),),),);}}8.AnimatedDefaultTextStyle - 文本样式动画classAnimatedDefaultTextStyleExampleextendsStatefulWidget{@override_AnimatedDefaultTextStyleExampleStatecreateState()=_AnimatedDefaultTextStyleExampleState();}class_AnimatedDefaultTextStyleExampleStateextendsStateAnimatedDefaultTextStyleExample{bool _isLarge=false;@overrideWidgetbuild(BuildContextcontext){returnGestureDetector(onTap:(){setState((){_isLarge=!_isLarge;});},child:AnimatedDefaultTextStyle(duration:Duration(milliseconds:300),style:_isLarge?TextStyle(fontSize:24,fontWeight:FontWeight.bold,color:Colors.red,):TextStyle(fontSize:16,fontWeight:FontWeight.normal,color:Colors.blue,),// 文本样式变化child:Text(_isLarge?'大文本':'小文本',),),);}}显式动画组件显式动画组件需要手动控制动画过程,使用 AnimationController 管理动画。1.AnimationController - 动画控制器classAnimationControllerExampleextendsStatefulWidget{@override_AnimationControllerExampleStatecreateState()=_AnimationControllerExampleState();}class_AnimationControllerExampleStateextendsStateAnimationControllerExamplewithSingleTickerProviderStateMixin{AnimationController_controller;@overridevoidinitState(){super.initState();_controller=AnimationController(duration:Duration(milliseconds:1000),// 动画持续时间vsync:this,// 垂直同步);}@overridevoiddispose(){_controller.dispose();super.dispose();}@overrideWidgetbuild(BuildContextcontext){returnColumn(children:[// 开始动画ElevatedButton(onPressed:(){_controller.forward();// 正向播放},child:Text('开始动画'),),// 反向动画ElevatedButton(onPressed:(){_controller.reverse();// 反向播放},child:Text('反向动画'),),// 停止动画ElevatedButton(onPressed:(){_controller.stop();// 停止动画},child:Text('停止动画'),),// 重置动画ElevatedButton(onPressed:(){_controller.reset();// 重置动画},child:Text('重置动画'),),],);}}2.Tween - 动画值范围classTweenExampleextendsStatefulWidget{@override_TweenExampleStatecreateState()=_TweenExampleState();}class_TweenExampleStateextendsStateTweenExamplewithSingleTickerProviderStateMixin{AnimationController_controller;Animationdouble_animation;@overridevoidinitState(){super.initState();_controller=AnimationController(duration:Duration(milliseconds:1000),vsync:this,);// 创建动画_animation=Tweendouble(begin:0,// 起始值end:1,// 结束值).animate(_controller);}@overridevoiddispose(){_controller.dispose();super.dispose();}@overrideWidgetbuild(BuildContextcontext){returnColumn(children:[// 开始动画ElevatedButton(onPressed:(){_controller.forward();},child:Text('开始动画'),),// 动画值显示Text('动画值:${_animation.value}'),// 使用动画值Container(width:100+_animation.value*100,// 宽度从100到200height:100+_animation.value*100,// 高度从100到200color:Color.fromRGBO(255,0,0,_animation.value,// 透明度从0到1),child:Center(child:Text('动画',style:TextStyle(color:Colors.white,fontSize:16,),),),