小菜前兩天學習了以下 Animation 的基本動畫,接下來小菜學習以下稍微進階版的 Animation 動畫。
複合動畫
小菜前兩天學習的主要是基本的單一動畫,當然多個動畫效果集一身也是毫無問題的,小菜接下來嘗試一個圖檔顯隐性和縮放同時循環使用的 Demo;
- addStatusListener 用來監聽目前動畫狀态,即開始或結束;
- addListener 用來堅挺動畫過程,可擷取實時 value 值;
AnimationController controller;
Animation<double> animation, sizeAnim;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = Tween(begin: 0.0, end: 1.0).animate(controller);
sizeAnim = Tween(begin: 0.0, end: 180.0).animate(controller);
animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
sizeAnim.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
}
Widget bodyWid() {
return Center(
child: Opacity(
opacity: animation.value,
child: FlutterLogo(size: sizeAnim.value)));
}
時間段動畫
既然可以監聽動畫過程和動畫狀态,整體的動畫便可以靈活掌握;小菜接下來嘗試一下分時間段動畫,前 50% 顯隐性處理,後 50% 縮放處理;
AnimationController controller;
Animation<double> animation, sizeAnim;
@override
void initState() {
super.initState();
controller = AnimationController(duration: const Duration(milliseconds: 2000), vsync: this);
animation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: controller, curve: Interval(0.0, 0.5, curve: Curves.ease)));
sizeAnim = Tween<double>(
begin: 100.0,
end: 180.0,
).animate(CurvedAnimation(
parent: controller,
curve: Interval(0.5, 1.0, curve: Curves.fastOutSlowIn)));
}
Widget bodyWid() {
return Center(
child: Opacity(
opacity: animation.value,
child: FlutterLogo(size: sizeAnim.value)));
}
自定義動畫
動畫是靈活的,我們可以根據自己的需求自定義動畫效果,小菜嘗試一個圓環繞一個圓轉圈;
AnimationController controller;
Animation<double> animation;
@override
void initState() {
super.initState();
controller = AnimationController(duration: const Duration(milliseconds: 2000), vsync: this);
animation = Tween(begin: -1.0, end: 1.0).animate(controller);
}
class AnimationCanvas extends CustomPainter {
Animation<double> animation;
AnimationCanvas(this.animation);
Paint _paint = Paint()
..color = Colors.blue
..strokeWidth = 4.0
..style = PaintingStyle.stroke;
@override
void paint(Canvas canvas, Size size) {
canvas.save();
canvas.drawCircle(Offset(300, 300.0), 150.0, _paint);
canvas.restore();
canvas.save();
canvas.translate(150 * sin(pi * animation.value), 150 * cos(pi * animation.value));
canvas.drawCircle(Offset(300, 300.0), 10.0, _paint..color = Colors.red);
canvas.restore();
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
Hero 動畫
Hero 動畫是 Flutter 提供的飛入式動畫,主要用在頁面間切換時動畫,且傳回時動畫按原路傳回;使用時設定兩個頁面間 tag 一緻即可,友善簡潔;
Widget bodyWid04() {
return Container(
child: Padding(
padding: EdgeInsets.all(10.0),
child: GestureDetector(
child: Row(children: <Widget>[
Hero(tag: 'user_header', child: FlutterLogo(size: 50.0)),
Padding(
padding: EdgeInsets.only(left: 12.0),
child: Text('Flutter Ptoto'))
]),
onTap: () {
Navigator.pushNamed(context, 'animateRoute01');
})));
}
小菜學習了一下稍進階的動畫,如果有問題的煩請多多指導!