一捕捂、隱式(全自動(dòng))動(dòng)畫
所謂隱式動(dòng)畫就是只需要設(shè)置動(dòng)畫目標(biāo)窟勃,過程控制由系統(tǒng)實(shí)現(xiàn)
一般是簡(jiǎn)單點(diǎn)的動(dòng)畫,比如只是簡(jiǎn)單的寬高變化遥皂。當(dāng)然使用簡(jiǎn)單不代表功能就簡(jiǎn)單力喷,下面會(huì)有體現(xiàn)
沒有循環(huán)重播刽漂,不用隨時(shí)中斷,沒有多方協(xié)調(diào)冗懦,就是從開始運(yùn)行到結(jié)束爽冕。
這種動(dòng)畫一般就是隱式動(dòng)畫仇祭,使用flutter提供的api披蕉,隱式動(dòng)畫一般是Animated...開頭。所以乌奇,便于學(xué)習(xí)記憶
還可以自定義隱式動(dòng)畫:TweenAnimationBuilder
AnimatedContainer
動(dòng)畫盒子没讲,是作用到盒子屬性上的,所以盒子有的一些屬性礁苗,是可以動(dòng)畫效果的爬凑。。但是每個(gè)widget都有自己的管理试伙,所以嘁信,如果想實(shí)現(xiàn)盒子里widget的動(dòng)畫就需要?jiǎng)e的方式了
實(shí)現(xiàn)很簡(jiǎn)單,就兩行代碼疏叨,AnimatedContainer潘靖,duration變量。flutter會(huì)隱式的幫我們處理動(dòng)畫過程蚤蔓。
實(shí)現(xiàn)簡(jiǎn)單卦溢,但是功能可不簡(jiǎn)單,container有個(gè)decoration屬性秀又,該屬性能實(shí)現(xiàn)的功能是很豐富的单寂。所以,只要是盒子這個(gè)級(jí)別的所有變化都是可以動(dòng)畫的
不同控件間切換的過渡動(dòng)畫:AnimatedSwitcher
依然是個(gè)widget吐辙,是個(gè)盒子宣决,但是該盒子是用于處理內(nèi)部child組件切換時(shí)候動(dòng)畫的。
也是只有一個(gè)屬性:duration昏苏。flutter會(huì)隱式幫我們處理動(dòng)畫過程
但是當(dāng)子組件沒有變化的時(shí)候尊沸,就沒有動(dòng)畫了
比如:AnimatedSwitcher內(nèi)的child組件是個(gè)text,text內(nèi)容有變化的時(shí)候捷雕,就不會(huì)有動(dòng)畫椒丧,這是因?yàn)閒lutter判斷child子組件沒有發(fā)生變化,就沒有觸發(fā)動(dòng)畫過程
所以救巷,只需要給組件設(shè)置一個(gè)key即可壶熏。可以如下簡(jiǎn)單的設(shè)置一下:UniqueKey浦译,表示自己唯一的key
key: UniqueKey()
demo
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: 200,
height: 300,
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 400),
//當(dāng)內(nèi)容有變化的時(shí)候就會(huì)觸發(fā)動(dòng)畫
child: Text('content', key: UniqueKey(),),
// 豐富的動(dòng)畫控制
transitionBuilder: (child, animation) {
return FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: animation,
child: child,
),
);
}
),
);
其他的一些可以自行嘗試
一般就是Animated...開頭的動(dòng)畫組件
- AnimatedOpacity
- AnimatedPadding
- ...
另外動(dòng)畫默認(rèn)是線性變化的棒假,動(dòng)畫有個(gè)curve屬性溯职,可以自行嘗試
TweenAnimationBuilder
demo
return TweenAnimationBuilder(
tween: Tween(begin: 0.0, end: 1.0),
duration: const Duration(seconds: 2),
builder: (context, double value, widget) {
return Opacity(
opacity: value,
child: Container(
width: 200,
height: 300,
color: Colors.red,
),
);
}
);
補(bǔ)充:平移動(dòng)畫饵撑,offset可以直接寫到tween里
二剑梳、顯示(手動(dòng)控制)動(dòng)畫
一般我們使用AnimationController的時(shí)候,直接在as中鍵入stanim使用模板代碼:
class xxx extends StatefulWidget {
const xxx({Key? key}) : super(key: key);
@override
_xxxState createState() => _xxxState();
}
class _xxxState extends State<xxx> with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
vsync:垂直信號(hào)粱侣,由于不同設(shè)備刷新頻率不一樣羊壹,告訴系統(tǒng)何時(shí)同步動(dòng)畫狀態(tài)。with SingleTickerProviderStateMixin齐婴。vsync:this即可
- controller是什么油猫?
動(dòng)畫控制器,是跟系統(tǒng)有綁定的關(guān)系柠偶,通過vsync:this實(shí)現(xiàn)屏幕刷新回調(diào)builder回調(diào)情妖。所以動(dòng)畫的實(shí)現(xiàn)最關(guān)心的是_controller持續(xù)的變動(dòng)以及builder回調(diào)刷新,具體的動(dòng)畫控制可以自行實(shí)現(xiàn)诱担,用Tween修改動(dòng)畫范圍
比如我們使用RotationTransition的時(shí)候turns參數(shù)就可以傳_controller毡证,turns的入?yún)⒕涂梢杂肁nimationController做一個(gè)映射,自己來控制轉(zhuǎn)的圈數(shù):turns:_controller.drive(Tween(end: 4))
這樣實(shí)現(xiàn)了_controller的duration內(nèi)旋轉(zhuǎn)4圈
同理其他...Transition以及AnimatedTransition也一樣可以這樣用蔫仙。比如FadeTransition料睛,opacity就可以直接用_controller。
另外可以addListener監(jiān)聽它的值變化,也可以用.value獲取動(dòng)畫過程中當(dāng)前值
- turns傳的controller怎么會(huì)是個(gè)double呢恤煞?
上面說的RotatationTransition屎勘,turns參數(shù)怎么可以用_controller呢?它是繼承自extends Animation<double>的居扒。
- ?
比如ScaleTransition概漱,scale入?yún)ween(),可以用_controller.drive(Tween())包裝為Animation<double>類型喜喂。作用就是_controller的duration范圍內(nèi)Tween補(bǔ)幀縮放范圍.
比如AlignTransition瓤摧,alignment入?yún)⑹茿nimation<AlignmentGeometry>類型,也可以用_controller.drive()驅(qū)動(dòng)
return SlideTransition(
position:_controller.drive(Tween(begin: Offset(0, 0), end: Offset(1, 1))),
);
return AlignTransition(
alignment: _controller.drive(Tween(begin: Alignment.topLeft, end: Alignment.bottomRight)),
child: const Text("d"),
);
- ticker是什么夜惭?
英文釋義是嘀嗒聲姻灶,形象的表述為屏幕刷新頻率,屏幕要刷新一幀的時(shí)候就發(fā)一個(gè)tick
AnimationController初始化的時(shí)候設(shè)置的duration范圍诈茧,有幾種控制方式:
1、初始化controller時(shí)候捂掰,設(shè)置lowerBound敢会,upperBound
2、scale:_controller.drive(Tween(begin:0.0, end:1.0))这嚣。
這種方式解決的是將Tween<double>轉(zhuǎn)為Animation<double>
3鸥昏、還有種寫法:交錯(cuò)動(dòng)畫
Tween(begin:Offset(0, -0.5), end:Offset(0, 8))
.chain(CurveTween(curve: Curves.elasticInOut))
.chain(CurveTween(curve: Interval(0.0, 0.2)))
.animate(_controller)
chain可以理解為一個(gè)函數(shù),就好比g(h(f(x)))姐帚,函數(shù)嵌套吏垮,_controller就像是動(dòng)畫的持續(xù)過程,這個(gè)是跟屏幕刷新有關(guān)罐旗,但是可以通過多函數(shù)復(fù)合作用于實(shí)際動(dòng)畫效果膳汪。比如上面的代碼:offset移動(dòng)和移動(dòng)速度曲線同時(shí)作用于動(dòng)畫過程,就有了從開始到結(jié)束沿移動(dòng)速度曲線進(jìn)行移動(dòng)的動(dòng)畫效果
自定義顯示動(dòng)畫:AnimatedBuidler
自定義顯示動(dòng)畫九秀,一是把動(dòng)畫控制交給AnimationController遗嗽,二是可以做一些性能優(yōu)化。比如把動(dòng)畫渲染過程中不需要重繪的組件交給AnimatedBuidler
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
//_controller控制內(nèi)持續(xù)的調(diào)用builder
builder: (context, child) {
//每次調(diào)用builder鼓蜒,內(nèi)部所有組件都會(huì)重新渲染痹换,注意考慮優(yōu)化性能
return Opacity(
//這里value超過1也沒關(guān)系,有自動(dòng)糾錯(cuò)機(jī)制都弹。并不會(huì)報(bào)錯(cuò)娇豫。透明度是0~1,如果超過1就還是1不透明的效果
opacity: _controller.value,
child: Container(
width: 300,
height: 200 + 100 * _controller.value,
color: Colors.red,
child: child,
),
);
},
//動(dòng)畫執(zhí)行過程中畅厢,不需要變化的部分可以傳給AnimatedBuilder冯痢,
// 每次builder回調(diào)時(shí)候會(huì)再傳出來,這樣就避免了child部分的重新渲染
child: const Center(
child: Text(
"hello",
style: TextStyle(fontSize: 24),
),
),
);
}
三、其他動(dòng)畫
Flutter動(dòng)畫背后的機(jī)制和原理
Hero動(dòng)畫
動(dòng)畫轉(zhuǎn)場(chǎng)更絲滑
但是貌似好像看不出hero動(dòng)畫的牛逼之處系羞,下面再看個(gè)例子:
hero動(dòng)畫有個(gè)特點(diǎn)郭计,就是觸發(fā)那一刻就變?yōu)槟繕?biāo)ui然后開始動(dòng)畫
功能強(qiáng)大,使用簡(jiǎn)單椒振,只需要在開始和目標(biāo)ui上包括Hero并設(shè)置相同唯一的tag即可
直接操作底層的CustomPaint
嵌入式lottie昭伸、Rive/Flare插件動(dòng)畫
體驗(yàn)了一下Rive在線動(dòng)畫平臺(tái),跟lottie是差不多的澎迎,支持的平臺(tái)也很全庐杨。動(dòng)畫制作交給美工就行了,具體實(shí)現(xiàn)夹供,都是加載json灵份。提供的都有插件.
https://rive.app.可以體驗(yàn)一下,制作一個(gè)簡(jiǎn)單的動(dòng)畫哮洽,設(shè)置時(shí)間節(jié)點(diǎn)的關(guān)鍵幀填渠,動(dòng)畫也有補(bǔ)幀動(dòng)畫的感覺