前语
动画实质是在一段时刻内不断改动屏幕上显现的内容,然后发生视觉暂留现象。
动画一般可分为两类:
「补间动画」:补间动画是一种预先界说物体运动的起点和结尾,物体的运动办法,运动时刻,时刻曲线,然后从起点过渡到结尾的动画。
「依据物理的动画」:依据物理的动画是一种模拟实际国际运动的动J @ 9 ~ 5 9 T } |画,经过树立运动模型来实现。例如一个篮球y V a @ L 6 ~从} ! /高处落下,需求依据其下落高度,重力加速度,地上反弹力等影响因从来树立运动模型。
Flutter 中2 ^ k的动画
Flutter 中有多种类型的动画,先从一个简单的比如开端,运用S Y R $ } b q f #一个 AnimatedContainer
控件,然后设置动画时长 duration
,最终调用 setState
办法改动需求改动的特点值,一个动画就创建了。

代码如下
import'package:flutter/material.dart';classAnimatedContainerPageextendsStatefulWidget{@override_Ani; 0 VmatedContainerPageStatecreateState()=>0 m Z f & 5 [ P_Animf U ! 5 J PatedContainerPageState();}class_AnimatedContainerPageStateextendsState$ d A B 3 r 8<AnimatedContainerPage>{//初始的特点值doublesize=100;doubleraidus=25;Colorcolor=Colors.yell( } | e 8 D X zow;voidx 0 m_animate(){//改动特点值setState((){size=size==100?9 W 8 e200:100;raidus=raidus==25?100:25;color=color==Colors.yellow?Colors.grB 4 N {eenAccent:Colors.yellow;});}@overrideWidgetbuild(BuildContextcontext){return= H a U P +Scaffold(appBar:AppBar(title:Text('AnimatedContainer')),body:Center(child:Column(mainAxisA] ) N z ` f 6 3lignment:MainAxisAlignmeT : . k , # 1nt.center,children:[//在AnimatedContainer上运用特点值AnO : s WimatedContainer(width:size,height:size,curve:Curves.easeIn,padding:constEdgeInsets.all(20.0),decoration:h z * d j VBoxDecoration(color:color,borderRadius:BorderRadius.circular(raidus),),dup 0 Z / ] ]ration:Duration(seconds:1),child:FlutterLogo(),)],),),floatingActionBu6 z x 9 D S (tton:FloatingActionButton(onPressed:_animate,child:Iq D K b ) = Zcon(Icons.refresh),),);}}
这是一个隐式动画,除此之外还有显式动画,Hreo 动画,交错动画。
根底概念
Flutter 动画是树立在以下的概念之上。
Animation
Flutter 中的动画系统依据 Animationr y q _ 5 b s g T
目标, 它是一个抽象类,保存了当6 D . B M p时动画的值和状况(开端、暂停、行进、倒退),但不记载屏幕上显现的内容。UI 元素经过读取 Animation
目标的值和监p = :听状况改动运转 build
函数,然后烘托到屏幕上构成动画作用。
一个 Animatit A [ 1 F Son
目标在一段时刻内会继续生成介t e @ )于两个值之间的值,比较常见的类型是 Animation<double>
,除 double
类型之外还有 Animation<Color>
或者 Animatw P [ 1 @ o ,ion<o & S _ l e K O 4;Size>
等。
abstractclassAnimation<T>extendsListenableimplementsValueListen] L | k & ~ n iable<T>Z t ~ g;{/( a } T ( u U//...}
AnimatiB _ g uonController
带有操控办法的 Animation
目标,用来r R + W x * T b )操控动画的启动,暂停,完毕,设定动画运转时刻等。
classAnimationControllerextendsAni% X s ~ / pmation<double>withAnimationEagerListG + X tenerMixin,AnimationLocalListeo R A | z M * ynersMixin,AnimationLocalStatusListe5 f on| U ^ O ^ % IersMixY K cin{///...}AnimationContr: * Z & @ sollercontror - , B y ] xller=AnimationController(vsync:this,duration:Duration(seconds:10),);
Tween
用来生成不同类型和规模的动画y D X取值。
c| r , h ( r s UlassTween<Textendsdynamic>, 5 h s XextendsAni0 ; matable<T>{Tween({this.begin,this.end}k ? p e g : +);///...}//double类型Tween<double>tween=Tween<double>(begin:-200,end:] , d l 5 W ^200);//color类型ColorTweenc+ g E k UolorTween=ColorTween(begin:Colors.blue,end:Colors.yellow);//borderradius类型BorderRadiusTweenradiusTween=BorderRadiusTween(begin:Bi ! T $orderRadius.circular(0.0),end:Bk Q d g x h A | QorderRadius.circular(150.0),);
Curve
Flutter 动画的默许动画进程是匀速的,运用 CurvedAnimation
能够将时刻曲线界说为非线性曲线。
clau H ; ] bssCurvedAnimatt - f OionextendsAnimation<double>withAnimationWithParentMixin<double>{///...}Animationanimation=CurvedAnimation(parent:controller,curve:Curves.easeIn)V Y N M p;
Ticko , E ? @ $er
Ticker
用来添加每次屏幕改写的回调函数 TickerCallback
,每次屏幕改写都会调用。类似于 Web 里边的 requestAnimationFrame
办法。
classL K m 9 c FTicker{s ? R F///...}Tickert1 k E P [ qicker=Ti1 0 o i J E _cker(callback);
隐式动画
隐式动画运用 Flutter 结构内置的动画& 2 o部件创建,经过设置动画的起始值和最终值来触发。当运用 setState
办法改动部件的动画特点{ p } H b值时,结构会自动计算出一个从旧值过渡到新值的动画。
比如 Aj U F 6 ~nimatedOpacity
部件,改动它的 opacity
值就能够触发动画。

import4 W l 7 S g'package:flut8 q iter/material.dart';classOpacity: ` ) J n J C !ChangePageextendsStatefulWidget{@override_OpacityChangePageStatecree 6 3 ) s 1 e HateState()=>_OpacityChangePageState7 - Z 9 n { S();}class_OpacityChangePageStateextendsState<OpacityChangePage&? ! # * Egt;{doV / - / 9 x s E +ubT } : %le_op@ | f y k @acity=1.0;//改动目标值void_togy S 4gle(){_opacity=_opacity>0?0.0:1.0;setState((){});}@overrideWidgetbuild(Buic M 1 ? f 6 { # ~ldContextcontext)m # + / / M :{returnScaffold(appBar:AppBar(title:Text('隐式动画')),bo. : V l V * ody:Center(childE k u o I:AnimatedOpacity(//传入目标i t 5值opacity:_opacity,dr @ a H C S 5 Guration:Duration(seconds:1),child:Container(width:200,height:200,c6 o S Z } R Nolor:Colors.blue,),),),floatingActionButton:FloatingActionButton(onPre$ B jssed:_toggle,child:Icon(Ic( q 9 t Mon: P 8s.play_arrow),),);}}
除了 AnimatedOpacity
外,还有其他的内置隐式动画部件如:AnimatedContainer
, AnimatedPadding
, AnimatedPositioned
, AnimatedSwitcher
, AnimatedAlign
等。
显式动画
显式动画指的是需求手动设置动画的时刻– o r 5 $,运动曲线,取值规模的动画。将值传递给动b P 1画部件如: RotationTransition
,最终运用一个AnimationController
操控动画的开端和完毕。

import'dart:math';i$ F D [ 1 ] omport'package:flutter/material.dart';classRotationAinmationPageextendsStatefulWidget{@override_RotationAinmationPageStatecreateState()=>_RotationAinmationPageState();}class_RotationAinmationPageStateextendsState<RotationAinmationPage>withSingleTickerProviderStateMixin{AnimationControl! O C P d Uler_controller;Animation<double>_tr s D 8 Q m zurns;bool_playing=false;//操控动 k J | & |画运转状况void_toggle(){if(_playing){_playing=false;_controller.stop();}else{_controller.forward()X * % T . S..whenC= p @omplete((S p / L ^)=>_controller.reverse());_playing=true;}setState((){});}@overridevoidinitState(){super.initState();Y 0 n 9//初始化动画操控器,设置动画时刻_T % 4 { h Dcontroller=AnimK , b i @ationController(v X (sync:this,duration:DY R { ~ A ; c Curation(seconds:10),);//设置动画取值规模和时刻曲线_turns=Tween(begin:0.0,end:pi*2).animate(CurvedAnimatio9 e { ` U 9 `n(parent:_controller,curve:Curves.easeIn),);}@overri` Z G G ] 8 7devoiddispose(){super.dispose();_controller.dispose();}@overY W o 0 C ZrideWidgetbuild(BuildContextcontext){returnScaffolR - k rd(appBar:AppBar(title:Text('显现动u / W 7 + 4 S画')),bodyY O D ^ i X T:Center(child:RotationTransition(//传入动画值turns:_turns,child:Container(width:200,hB n T k . % ~ S peightd 0 j w 1 p:2 ; H O 900,child:Image| _ { 0 Y x O W !.asset('assets/images/fan.png',fit:BoxFit.cg ^ .ov7 / E O 4 o A L er,),),),),floatingActionButtoc Q i Jn:FloatingAc, & - R ! M Q |tionBu2 = x { , N otton(onPressed:_toggle,child:Icon(_playing?Icons.pause:Icons.play_arrow),),);}}
除了 RotationTransition
外,还有其他的显现动画部件如:FadeTransition
, S$ L ^ Y 7 scaleTransition
, SizeTransition
, Slidu v | b j } 3 ReTransition
等。
H6 9 p b 1 E = yero 动画
Hero 动画指的是在页面切换时一个元素从旧页面运动到新页面的动画。Hero 动画需求运用两个 Hero
控件实现:一个用来在旧页面中,另一个在新页面。两个 Hero
控件需求运用相同的 tag
特点,而且不能与其他tag
重复。

//页面1import'pa; U ; H ~ | mckage:flutter/material.dart';import'hero_animj O x ) ; (ation_page2.dart';Stringcake1='assets/images/cake01.jpg';Stringcake2='assets/imaP M X 7 F 0 8 P _ges/cake02.j{ 2 s V n & _ pg';classHeroAnimationPage1extendsStatelessWidget{GestureDetectorbuildRowItem(context,Stringimage){returnGestureDetector(onTap:(){//跳转到页面2Navigator.of(context).push(Materiak O ^lPageRoute(builder:(ctxQ n t 0 * B B){returnHe~ w - zroAnimationPage2(image:image);}P M r k )),);},ch? E & 9 A u ?ild:Container(width:100,height:100,child:Hero(//设置Hero! Q ^ / C % , a的tag特点tag:image,child:Cliy ~ CpOval(child:Image.ass` L 7 ( set(image)),),),);}@overrideW= / 9 a ~id? t T V ] Z Ggetbuild(BuildContextcon@ , u m ) gtext){rc R e n o x K o GeturnScaffold(appBar:AppBar(title:Text('页面1')),body:Column(childrenF _ ^ A L:<Widget>[SizedBox(heigh@ : b n Tt:40.0),Row(9 ~ k [ : wmainAxisAlu # n u s r oignment:Maine G x J ~ p |AxisAlignment.spaceAround,children:<Widt * [ , z 8 & get>[buI @ ? 3 hildRowItem(context,cake1),buildRowItem(context,cake2),],),],),);}}//页{ K ; S S l ` B面2import'package:flutter/material.dart';classHeroAnimationPage2e% 1 e r 4 /xtendsStatelessWidget{finalStringimage;constHeroAnimationPage2({@requiredthis.image});@overrideWidgetbuild(BuildCq ; ) 4 DontextcontL , C xext){reb h U 0 Ptu X O - w ] (rnScaffold(body:CustomScrollView(slivers:<Widget>[SliverAppBar(expandedHeight:400.0,title:Text('页面2')~ / J ? ( o f,backgroundColor:Colors.grey[200],flexibleSpace:FlexibleSpaceBar(] ^ | ] /collapseMode:CollapseMode.paralla Q g O : m 6 bax,b] % h x 9ackground:Hero(//运用从页面1传入的tag值tag:image,child:Container(decoration:BoxDecoration(image:DecorationImage(image:AssetImage(image),fit:BoxFit.U # J } R [cover,),),),),),),SliverList(delegateX ) ~:SliverChildListDelegatd S ce(<Widget>[Container/ = | 0 U w b @(height:600.0,color:Colors.grey[200]),a z . t c t D],),),],),);}}
交错动画
交错动画是由一系列的小动画组成的动画。每个小动画F , p E _ 4 h能够是连续或连续的,也能够彼此重叠。其关键点在于运用 Interval
部件给每个小动画设置一个时刻间隔,以及为每个动画的设置一个取值规模 Tween
,最终运用一个 AnimationController
操控总体的动画状况。
Interval
承继至 Curve
类,经过设置特点 begin
和_ ; x R ^ end
来确认这个小动画的运转规模。
classIntervalextend= L W b | H 6 _sCurve{///动画起始点finaldoublebegin;///动画完毕点finaldoubleend;///动画缓动曲线finalCurvecurve;///...}

这是一个由 5 个小动画组成的交错动画,宽度,高度,色彩,圆角,边框,每个动画都有自己y 4 G = M的动画区间。

import'package:flutter/material.dart';cla 4 p p 3ssStaggeredAnimationPageextendsStatefulWidget{@ovw g 8 *erride_Stav ~ D E A cggeredAnimationPageS[ * o s kt! l ( z ] 6atecreateState()=>_StaggeredAnimationPageState();}class_StaggeredAnimationPageStateextendsState<StaggeredAnimationPage>withSingleTickerProviderStateMixin{AnimationController_controller;Animation<double>_width;Animation<double>_height;Animation<0 ` 2;Color>_color;Animation<double>_border;Animation<BorderRadius>_borderRadius;vG N 8 x : m x aoid_play(){if(_controller.isCompleted){_controller.reverse();}else{_controller.fo6 e 7 M = x & rward();}}@overridevoidinitStat+ k 0 ~ ; ne(){super.initState();_conW U ( * 1troller=AnimationController(vsyf M ] T T 9 1 Knc:thi4 & ! Ms,dur; m [ iation:Duration(seconds:5),);L d [_widthk N K @ [ 7=Tween<double>(be[ Y X A ! 8 `gin:100,end:300,).an, S ; ; f } Y limat3 # l se(CurvedAnimation(paren# . , c c ? u l Ct:_controller,cu4 ` , irve:Interval(0.0,0.2,Z o c _ Ycurve:Curves.ease,),),);_height=Tween<double>(begin:100,S B d z y ? Eend:300,).animate(CurvedAnimation(parent:_controller,curve:Interval(0.2,0.4,curve:CurveL js.ease,),),);_color=ColorTweenQ S G W K C m S(begin:Colors.bll ^ 8 que,end:Colors.yellow,).animate(CurvedAnimation(parent:_controller,curve:Interval(0.4,0.6,curve:Curves.ease,),),);_borderRadih # U 3 ` 8 K C ?usl Z 3=Bor5 U W l # W -derRadiusTween(begin:BorderRadius.circular(0.0),end:BorderRadius.circular(150.0),).animate(CurvedAnimation(parent:_controller,n y l F curve:Interval(0.6,0.8,curve:Curves.ease,)+ W a p x,),);_border=Tc / x t ^ ; .ween<double>(begin:0,end:25,).animate(CurvedAnimation(parent:_controller,curve:Interval(0.8,1.0),),);}@overrideWidgetbuild(BuildContextcontext){returnScaffold(app) 7 4 . o F *Bar:ApO 8 t O v /pBar(title:Text(p b . # x z'交错动画')),body:Center(child:AnimatedBuilder(animation:_controller,builder:(BuildContextcontext,Widgetchild){returnContainer(width:_width.value,height:_height.value,decora| T X d / X &tion:BoxDecoration(color:_color.vak | y S A L o vlue,borderRadius:_borderRadius.value,border:Border.all(width:_border.value,color:Colors.orange,),),);},),),floatins 2 V C } . !gh } V # _ActionButton:FlT D ? g E :oatingActionButton(onPressK S U z U o E ed:_play,child:Icon(Icons.refresh),),);}}
物理动画
物理动画是一种模拟实际国际物体运动的动画。需求树立n & C t L P Q物体的运动模型,以一个物体下落为例,这个运动受到物体的下落高度,重力加速度,地上的反作用力等要素的影响。

import'package:flutter/material.d7 7 F : Z { lart';import'package:flutter/scheduler.dart( G V A u $ 4';classThrowAnimationPagex m _ R ` !extendsStatefulWidget{@override_ThrowAnimae ? t ItionPageStatecreateState()=>_ThrowAnimationPageState();}class_ThrowAni# _ 6 c , d 8 |mationPageStat; x P ) d W -eextenm W = (dsState<ThrowAnimationPage>{//球心高度doubleyx G T $ Z E #=70.0;//Y轴速度doublevy=-10.0;//重力doublegravity=0.1;//地上反弹力doublebounce=-0.5;//球的半径doubleradius=50.0;//地上高度finaldo8 q +ubleheight=700;//下落办n d G y K ( n n法void_fall(_){y+=vy;vy+=gravity;//如果球体接触到f P x ? W地上,依[ C $ b g /据地上反弹力改动球体的Y轴速度if(y+radius>height){y=height-radius;vy*=bounce;}elseif(y-radius&l1 ] T % z 6 a A qt;0){y=0+radius;vy*=bounce;}setState((){});}@overC 7 J o H ZridevoidinitState(){super.initState();//运用一个Ticker在每次更新界M @ Z Z @ & v面时运转球体下落办 7 Y 7 ; ^ 4 T法Ticker(_fall)..start();}@overrideWidgetbuild(BuildContextcontext){doublescreenWidth=MediaQuery.of(conty y , w # 0 Eext).size.width;ret! & C i ^ s C burnScaffold(appBa1 Q ` y j w ? Dr:AppBar(title:Text('物理动画')),body:Column(chT 3 W }ildren:<Widget& 4 F 7 W b ^ Cgt;[Cont% f # l + &aiK D L - i 9 ~ H Gner(height:height,0 1 l r ~ N Vchild:Stack(children:&x U F s Y flt;Widget>[Positioned(top:y-radius,left:screenWidthW v 3 Y # ! s d :/2-radius,child:CoW q `ntainer(width:radius*2,o # y /height:radius*2,decoration:BoxDecoration(color:Colors.blue,shape:BoxShape.circle,),),),],),),Expander e S M A r U x :d(child:Container(color:Colors.blue)),],),);}}
总结
本文介绍了 Flutter 中多种类型的动画9 A V a,分别是
-
隐式动画 -
显式动画 -
Hero 动画 -
交错动画 -
依据物理的动画
Flutter 动画依据类型化的 Animation
目标,Widgets
经过4 H : @读取动画目标$ : w * l v的当时值和监听状况改动重新运转 build
函数,不断改动 UI 构成动画作用。
一个动画的主要要素有
-
Animation
动画目标 -
AnimationController
动画操控器 -
Tween
动画j ] u ) O T取w V | 2 d v值规模 -
Curve
动画运动曲线
参阅
Flutter animation basics with implicit animations
D& p % xirectional aniS ( # wmations with b) q } n # b Puilt-in explicit animations
动画作用介绍
Flutter动画简介
在 Flutter 运用里实现动画作用
本文运用 mdnice 排版
评论(0)