如果你需要的不只是單向的動畫,想要控制更多動畫細節,Flutter 內建了一些 AnimatedWidget 的子類別,這些可以在 API 文件中查詢,像是 ScaleTransition
、RotationTransition
、PositionedTransition
等。
類似地,內建的隱式動畫 Widget 沒辦法滿足時,你可以進一步使用 TweenAnimationBuilder,必要時將實作細節封裝為 ImplicitlyAnimatedWidget
的子類;若內建的顯式動畫 Widget 沒辦法滿足時,也可以進一步使用 AnimatedBuilder
,必要時將實作細節封裝為 AnimatedWidget
的子類。
來看個使用 AnimatedBuilder
的例子,在〈TweenAnimationBuilder〉中的染色範例,只會單向地播放,若想要重複不停、往復式地播放,可以如下撰寫:
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: Caterpillar(),
)
);
class Caterpillar extends StatefulWidget {
@override
State<StatefulWidget> createState() => _CaterpillarState();
}
class _CaterpillarState extends State<Caterpillar> with SingleTickerProviderStateMixin {
var start = false;
AnimationController _animation;
@override
void initState() {
super.initState();
_animation = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..stop();
}
@override
void dispose() {
_animation.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('openhome.cc'),
),
body: Center(
// 使用 AnimatedBuilder
child: AnimatedBuilder(
animation: _animation,
builder: (_, __) {
return Image(
image: NetworkImage('https://openhome.cc/Gossip/images/caterpillar.jpg'),
// 將 AnimationController 的 value 轉為特性
color: Color.lerp(Colors.white, Colors.red, _animation.value),
colorBlendMode: BlendMode.colorBurn,
);
}
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
start = !start;
if(start) {
_animation.repeat(reverse: true);
}
else {
_animation.stop();
}
}),
tooltip: start ? 'Stop' : 'Start',
child: Icon(start ? Icons.stop : Icons.play_arrow),
),
);
}
}
大部份需要的實作,與〈TweenAnimationBuilder〉中談到的是相同的,AnimatedBuilder
的 builder
,第一個參數是 BuildContext
,第二個參數是 child
,也就是必要時,也可以指定 AnimatedBuilder
的 child
,這會傳入 builder
指定的函式中,重複使用以增進效能。
最主要的不同是,你要將 AnimationController
的 value
轉為目標特性,這邊使用了 Color.lerp
,指定的參數分別是 begin
、end
以及 t
,你可能會想:「嗯?該怎麼套用動畫曲線呢?」,實際上,這等於套用 Curves.linear
,之後再套用 ColorTween
,這需要接觸更多動畫細節,留待之後的文件再來討論。
來看一下執行效果: