Flutter 中的動(dòng)畫由 Animation、Curve、Controller、Tween共同組成,每一個(gè)組件都有他們特定的職責(zé),
下面我們一個(gè)一個(gè)介紹
AnimationController
AnimationController({
double value,
///動(dòng)畫過渡時(shí)間
this.duration,
this.reverseDuration,
this.debugLabel,
///動(dòng)畫開始的值
this.lowerBound = 0.0,
///動(dòng)畫結(jié)束的值
this.upperBound = 1.0,
this.animationBehavior = AnimationBehavior.normal,
///用來改變過程中的value的
@required TickerProvider vsync,
})
AnimationController用于控制動(dòng)畫,它包含動(dòng)畫的正向執(zhí)行forward()、停止stop() 、反向播放 reverse()等方法。他的區(qū)間是(0~1) 不可以超過這個(gè)區(qū)間 ,并在預(yù)定時(shí)間內(nèi)將這個(gè)數(shù)據(jù)不斷的由一端過度到另一端,每一幀都會(huì)生成一個(gè)新的值,這個(gè)過度的速度是由Curve 來控制的, 屏幕每一次刷新都是一幀,每一幀都會(huì)調(diào)用 TickerProvider來刷新當(dāng)前的動(dòng)畫的過渡值,并利用這個(gè)過渡值來構(gòu)建當(dāng)前的動(dòng)畫狀態(tài)
AnimationController 可以使用addListener 可以獲取動(dòng)畫過渡的值,addStatusListener 可以監(jiān)聽狀態(tài)發(fā)生改變,
如果想要重復(fù)執(zhí)行一個(gè)正向動(dòng)畫 forward(),
_controller
..value=0
..forward();
注意這里如果想要每次都執(zhí)行這個(gè)動(dòng)畫,必須重置這個(gè)value,這個(gè)問題困擾了我很久,
并且在widget 的dispose 的方法內(nèi)取消注冊(cè)
@override
void dispose() {
animatedContainer.dispose();
super.dispose();
}
TickerProvider 用來改變過程中的value的,使用的方法是 混入到需要的widget 中,通常為 SingleTickerProviderStateMixin,具體的作用原理還不是很理解,這里只能后來再完善了
Animation
Animation 是一個(gè)抽象類,他保存了動(dòng)畫的插值和狀態(tài),他在一定時(shí)間內(nèi)依次生成Tween之間的值,獲取的這個(gè)值可以是均勻的,也可是先快后慢等 ,這是由Curve決定的 ;動(dòng)畫不僅正向運(yùn)行,也可以反向運(yùn)行,一些比較常用的Animation 類比如Animation <double> ,Animation <Size>,Animation <Color>,Animation <Offset>等,這里我們需要記住一個(gè)比較重要的知識(shí)點(diǎn),那就是Animation 存了動(dòng)畫的插值和狀態(tài),我們可以按照動(dòng)畫正向即從0~1開始執(zhí)行,如果我們想要獲取 0.5的時(shí)候的值,則使用Tween.transform 則可以獲得,這是一個(gè)非常重要的點(diǎn).
Curve
Curve是用來控制動(dòng)畫執(zhí)行的速度的,flutter 中就是利用Curve來控制這個(gè)速度,并把勻速的線性動(dòng)畫稱為
Curves.linear ,將AnimationController利用CurvedAnimation 進(jìn)行包裝,
例子
animatedContainer = AnimationController(
duration: Duration(seconds: 2),
lowerBound: 0,
upperBound: 1,
vsync: this);
///改變起始值
Animation curve =
CurvedAnimation(parent: animatedContainer, curve: Curves.easeIn,);
Tween
默認(rèn)情況下AnimationController的數(shù)據(jù)是否0-1執(zhí)行的,但是我們需要將它放大到0-100怎么執(zhí)行呢,這里使用
Tween 改變起始值就可以了,并使用tween.animate()來獲取動(dòng)畫對(duì)象
例子
_tween=IntTween(begin: 0, end: 255)
anim=_tween.animate(_tween);
同樣可以封裝ColorTween
tween=ColorTween(begin: widget.begin,end: widget.end) ;
anim=tween.animate(CurvedAnimation(parent: _controller,curve: Curves.easeOut));
下面寫一個(gè)簡(jiǎn)單的例子
這個(gè)例子是控制文本的顏色Color.fromARGB(animation.value, 1, 1, 1),只需要從0-255 之間就可以了
然后先正向執(zhí)行,再反向執(zhí)行無(wú)限重復(fù)這個(gè)動(dòng)畫,
class _TsmAnimationState extends State<TsmAnimationPage>
with SingleTickerProviderStateMixin {
Animation<int> animation;
AnimationController animatedContainer;
@override
void initState() {
animatedContainer = AnimationController(
duration: Duration(seconds: 2),
lowerBound: 0,
upperBound: 1,
vsync: this);
///添加變速模型
Animation curve =
CurvedAnimation(parent: animatedContainer, curve: Curves.easeIn,);
///改變起始值
animation = IntTween(begin: 0, end: 255).animate(curve);
animatedContainer.addListener(() {
setState(() {
printString("value:${animation.value}");
});
});
animatedContainer.addStatusListener((status) {
if(status==AnimationStatus.completed){
animatedContainer.reverse();
}else if(status==AnimationStatus.dismissed){
animatedContainer.forward();
}
});
animatedContainer.forward();
super.initState();
}
@override
void dispose() {
animatedContainer.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Animation 學(xué)習(xí)"),
centerTitle: true,
),
body: Container(
child: Center(
child: Text(
"重復(fù)漸隱動(dòng)畫",
style: TextStyle(
color: Color.fromARGB(animation.value, 1, 1, 1),
),
),
),
),
);
}
}
效果圖

我學(xué)習(xí)flutter的整個(gè)過程都記錄在里面了
http://m.itdecent.cn/c/36554cb4c804
最后附上demo 地址