公司动态

Staggered交错动画:Flutter在鸿蒙平台实现有序动画序列

📅 2026/7/22 21:40:32
Staggered交错动画:Flutter在鸿蒙平台实现有序动画序列
作者付文龙红目香薰仓库地址https://gitcode.com/feng8403000/FlutterfromBeginnertoAdvancedForHarmonyOS.git联系邮箱372699828qq.com概述Staggered动画交错动画是一种将多个动画按照时间顺序依次执行或部分重叠执行的动画技术。它能够创造出富有层次感和节奏感的视觉效果是现代UI设计中常用的动画手法。Staggered动画核心概念什么是Staggered动画Staggered动画指的是多个动画按照一定的时间间隔依次开始形成一种波浪式的视觉效果。这种动画方式能够引导用户的注意力增强界面的交互体验。Interval时间间隔在Flutter中实现Staggered动画的核心是Interval类它定义了动画执行的时间范围Interval(double begin,double end,{CurvecurveCurves.linear})begin动画开始时间占总时长的比例0.0-1.0end动画结束时间占总时长的比例0.0-1.0curve动画曲线基础Staggered动画实现创建交错淡入动画classStaggeredFadeAnimationextendsStatefulWidget{constStaggeredFadeAnimation({super.key});overrideStateStaggeredFadeAnimationcreateState()_StaggeredFadeAnimationState();}class_StaggeredFadeAnimationStateextendsStateStaggeredFadeAnimationwithSingleTickerProviderStateMixin{lateAnimationController_controller;lateAnimationdouble_fadeAnimation1;lateAnimationdouble_fadeAnimation2;lateAnimationdouble_fadeAnimation3;overridevoidinitState(){super.initState();_controllerAnimationController(duration:constDuration(seconds:2),vsync:this,);_fadeAnimation1Tweendouble(begin:0,end:1).animate(CurvedAnimation(parent:_controller,curve:constInterval(0.0,0.3,curve:Curves.easeOut),),);_fadeAnimation2Tweendouble(begin:0,end:1).animate(CurvedAnimation(parent:_controller,curve:constInterval(0.2,0.6,curve:Curves.easeOut),),);_fadeAnimation3Tweendouble(begin:0,end:1).animate(CurvedAnimation(parent:_controller,curve:constInterval(0.4,1.0,curve:Curves.easeOut),),);_controller.forward();}overridevoiddispose(){_controller.dispose();super.dispose();}overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText(交错淡入动画)),body:Column(mainAxisAlignment:MainAxisAlignment.center,children:[FadeTransition(opacity:_fadeAnimation1,child:constFlutterLogo(size:100)),constSizedBox(height:20),FadeTransition(opacity:_fadeAnimation2,child:constFlutterLogo(size:100)),constSizedBox(height:20),FadeTransition(opacity:_fadeAnimation3,child:constFlutterLogo(size:100)),],),);}}复杂Staggered动画组合组合多种动画效果classComplexStaggeredAnimationextendsStatefulWidget{constComplexStaggeredAnimation({super.key});overrideStateComplexStaggeredAnimationcreateState()_ComplexStaggeredAnimationState();}class_ComplexStaggeredAnimationStateextendsStateComplexStaggeredAnimationwithSingleTickerProviderStateMixin{lateAnimationController_controller;lateAnimationdouble_fadeAnimation;lateAnimationdouble_slideAnimation;lateAnimationdouble_scaleAnimation;overridevoidinitState(){super.initState();_controllerAnimationController(duration:constDuration(seconds:2),vsync:this,);_fadeAnimationTweendouble(begin:0,end:1).animate(CurvedAnimation(parent:_controller,curve:constInterval(0.0,0.3,curve:Curves.easeOut),),);_slideAnimationTweendouble(begin:-50,end:0).animate(CurvedAnimation(parent:_controller,curve:constInterval(0.2,0.6,curve:Curves.easeOut),),);_scaleAnimationTweendouble(begin:0.5,end:1).animate(CurvedAnimation(parent:_controller,curve:constInterval(0.4,1.0,curve:Curves.easeOut),),);_controller.forward();}overridevoiddispose(){_controller.dispose();super.dispose();}overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText(复杂交错动画)),body:Center(child:AnimatedBuilder(animation:_controller,builder:(context,child){returnOpacity(opacity:_fadeAnimation.value,child:Transform.translate(offset:Offset(_slideAnimation.value,0),child:Transform.scale(scale:_scaleAnimation.value,child:constFlutterLogo(size:200),),),);},),),);}}列表交错动画动态列表项动画classStaggeredListAnimationextendsStatefulWidget{constStaggeredListAnimation({super.key});overrideStateStaggeredListAnimationcreateState()_StaggeredListAnimationState();}class_StaggeredListAnimationStateextendsStateStaggeredListAnimation{finalListStringitemsList.generate(10,(index)Item${index1});overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText(列表交错动画)),body:ListView.builder(itemCount:items.length,itemBuilder:(context,index){returnStaggeredListItem(index:index,text:items[index]);},),);}}classStaggeredListItemextendsStatefulWidget{finalint index;finalStringtext;constStaggeredListItem({super.key,requiredthis.index,requiredthis.text});overrideStateStaggeredListItemcreateState()_StaggeredListItemState();}class_StaggeredListItemStateextendsStateStaggeredListItemwithSingleTickerProviderStateMixin{lateAnimationController_controller;lateAnimationdouble_animation;overridevoidinitState(){super.initState();_controllerAnimationController(duration:constDuration(milliseconds:500),vsync:this,);_animationTweendouble(begin:100,end:0).animate(CurvedAnimation(parent:_controller,curve:Curves.easeOut),);Future.delayed(Duration(milliseconds:widget.index*100),(){_controller.forward();});}overridevoiddispose(){_controller.dispose();super.dispose();}overrideWidgetbuild(BuildContextcontext){returnAnimatedBuilder(animation:_animation,builder:(context,child){returnTransform.translate(offset:Offset(_animation.value,0),child:ListTile(title:Text(widget.text)),);},);}}Staggered动画进阶技巧使用StaggeredAnimationBuilder虽然Flutter没有内置的StaggeredAnimationBuilder但可以封装一个classStaggeredAnimationBuilderextendsStatefulWidget{finalint count;finalDurationduration;finalDurationdelay;finalWidgetFunction(int index,Animationdoubleanimation)builder;constStaggeredAnimationBuilder({super.key,requiredthis.count,requiredthis.duration,requiredthis.delay,requiredthis.builder,});overrideStateStaggeredAnimationBuildercreateState()_StaggeredAnimationBuilderState();}class_StaggeredAnimationBuilderStateextendsStateStaggeredAnimationBuilder{ListAnimationdouble_animations[];ListAnimationController_controllers[];overridevoidinitState(){super.initState();_animations[];_controllers[];for(int i0;iwidget.count;i){AnimationControllercontrollerAnimationController(duration:widget.duration,vsync:this,);AnimationdoubleanimationTweendouble(begin:0,end:1).animate(CurvedAnimation(parent:controller,curve:Curves.easeOut),);_controllers.add(controller);_animations.add(animation);Future.delayed(widget.delay*i,(){controller.forward();});}}overridevoiddispose(){for(varcontrollerin_controllers){controller.dispose();}super.dispose();}overrideWidgetbuild(BuildContextcontext){returnColumn(children:List.generate(widget.count,(index){returnwidget.builder(index,_animations[index]);}),);}}交互式Staggered动画classInteractiveStaggeredAnimationextendsStatefulWidget{constInteractiveStaggeredAnimation({super.key});overrideStateInteractiveStaggeredAnimationcreateState()_InteractiveStaggeredAnimationState();}class_InteractiveStaggeredAnimationStateextendsStateInteractiveStaggeredAnimationwithSingleTickerProviderStateMixin{lateAnimationController_controller;overridevoidinitState(){super.initState();_controllerAnimationController(duration:constDuration(seconds:2),vsync:this,);}overridevoiddispose(){_controller.dispose();super.dispose();}void_playAnimation(){_controller.reset();_controller.forward();}overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText(交互式交错动画)),body:Column(children:[Expanded(child:StaggeredAnimationBuilder(count:5,duration:constDuration(milliseconds:500),delay:constDuration(milliseconds:100),builder:(index,animation){returnFadeTransition(opacity:animation,child:FlutterLogo(size:80index*20),);},),),ElevatedButton(onPressed:_playAnimation,child:constText(播放动画)),],),);}}Staggered动画性能优化避免过度绘制对于大量列表项的交错动画使用RepaintBoundary减少重绘AnimatedBuilder(animation:_animation,builder:(context,child){returnRepaintBoundary(child:Transform.translate(offset:Offset(_animation.value,0),child:child,),);},child:constListTile(title:Text(Item)),)复用AnimationController对于简单的交错动画可以考虑复用AnimationController_controllerAnimationController(duration:constDuration(milliseconds:500*itemCount),vsync:this,);for(int i0;iitemCount;i){animations.add(Tweendouble(begin:0,end:1).animate(CurvedAnimation(parent:_controller,curve:Interval(i/itemCount,(i1)/itemCount,curve:Curves.easeOut,),),));}鸿蒙平台测试建议在鸿蒙平台测试Staggered动画时建议关注以下几点动画同步验证多个动画的时间间隔是否准确性能表现大量列表项动画的流畅度内存使用长时间运行动画的内存占用动画重置多次播放动画的正确性总结Staggered动画是一种强大的动画技术能够创造出富有层次感的视觉效果。通过Interval类定义动画的时间范围可以精确控制多个动画的执行顺序。在实际应用中Staggered动画常用于列表项入场、页面元素依次显示等场景。掌握Staggered动画的实现方式能够为应用增添更加生动的交互体验。