1.線性動畫
import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: AnimateApp(), ); } } class AnimateApp extends StatefulWidget { @override State<StatefulWidget> createState() { return _AnimateAppState(); } } class _AnimateAppState extends State<AnimateApp> with SingleTickerProviderStateMixin { AnimationController controller; Animation<double> animation; @override void initState() { super.initState(); // 創建 AnimationController 對象 controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 2000)); // 通過 Tween 對象 創建 Animation 對象 animation = Tween(begin: 50.0, end: 200.0).animate(controller) ..addListener(() { // 注意:這句不能少,否則 widget 不會重繪,也就看不到動畫效果 setState(() {}); }); // 執行動畫 controller.forward(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'AnimateApp', theme: ThemeData( primaryColor: Colors.blue ), home: Scaffold( appBar: AppBar( title: Text('AnimateApp'), ), body: Center( child: Container( // 獲取動畫的值賦給 widget 的寬高 width: animation.value, height: animation.value, decoration: BoxDecoration( color: Colors.redAccent ), ), ) ) ); } @override void dispose() { // 資源釋放 controller.dispose(); super.dispose(); } }
2.非線性動畫,在1.的基礎上修改部分代碼
controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 2000)); // 非線性動畫 final CurvedAnimation curve = CurvedAnimation( parent: controller, curve: Curves.elasticOut); animation = Tween(begin: 50.0, end: 200.0).animate(curve) ..addListener(() { setState(() {}); });
3.給 Animation
添加 addStatusListener(...)
來監聽當前動畫的狀態,如:動畫是否播放完成。我們可以給上面的例子加一個狀態監聽,讓動畫無限執行:
animation = Tween(begin: 50.0, end: 200.0).animate(curve) ..addListener(() { setState(() {}); }) ..addStatusListener((status) { if (status == AnimationStatus.completed) { controller.reverse(); } else if (status == AnimationStatus.dismissed) { controller.forward(); } });
AnimationStatus.completed
表示動畫在結束時停止的狀態,這個時候我們讓動畫反向執行(從后往前);
AnimationStatus.dismissed
表示動畫在開始時就停止的狀態,這個時候我們讓動畫正常執行(從前往后)。這樣就可以讓動畫無限執行了。
4.
Tween
還可以接受
Color
類型的參數,實現顏色漸變的效果,下面讓 widget 的顏色從 紅色 漸變到 藍色
Animation<Color> animation;
controller = AnimationController( duration: const Duration(milliseconds: 3000), vsync: this); animation = ColorTween(begin: Colors.redAccent, end: Colors.blue).animate( controller) ..addListener(() { setState(() {}); }); controller.forward(); ... child: Container( decoration: BoxDecoration( color: animation.value ), margin: EdgeInsets.symmetric(vertical: 10.0), height: 200.0, width: 200.0, ),
最后的例子
import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: AnimateApp(), ); } } class AnimateApp extends StatefulWidget { @override State<StatefulWidget> createState() { return _AnimateAppState(); } } class _AnimateAppState extends State<AnimateApp> with SingleTickerProviderStateMixin { AnimationController controller; // Animation<double> animation; Animation<Color> animation; @override void initState() { super.initState(); // 線性 // // 創建 AnimationController 對象 // controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 2000)); // // 通過 Tween 對象 創建 Animation 對象 // animation = Tween(begin: 50.0, end: 200.0).animate(controller) // ..addListener(() { // // 注意:這句不能少,否則 widget 不會重繪,也就看不到動畫效果 // setState(() {}); // }); //// 非線性 // controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 2000)); //// 非線性動畫 // final CurvedAnimation curve = CurvedAnimation(parent: controller, curve: Curves.elasticOut); // animation = Tween(begin: 50.0, end: 200.0).animate(curve) // ..addListener(() { // setState(() {}); // }); // 通過給 Animation 添加 addStatusListener(...) 來監聽當前動畫的狀態 // // 非線性 // controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 2000)); // // 非線性動畫 // final CurvedAnimation curve = CurvedAnimation(parent: controller, curve: Curves.elasticOut); // animation = Tween(begin: 50.0, end: 200.0).animate(curve) // ..addListener(() { // setState(() {}); // }) // ..addStatusListener((status) { // if (status == AnimationStatus.completed) {//表示動畫在結束時停止的狀態 // controller.reverse();//動畫反向執行(從后往前) // } else if (status == AnimationStatus.dismissed) {//表示動畫在開始時就停止的狀態 // controller.forward();//動畫正常執行(從前往后) // } // }); // Tween 還可以接受 Color 類型的參數,實現顏色漸變的效果,下面讓 widget 的顏色從 紅色 漸變到 藍色 controller = AnimationController(duration: const Duration(milliseconds: 3000), vsync: this); animation = ColorTween(begin: Colors.redAccent, end: Colors.blue).animate(controller) ..addListener(() { setState(() {}); }) ..addStatusListener((status) { if (status == AnimationStatus.completed) {//表示動畫在結束時停止的狀態 controller.reverse();//動畫反向執行(從后往前) } else if (status == AnimationStatus.dismissed) {//表示動畫在開始時就停止的狀態 controller.forward();//動畫正常執行(從前往后) } }); // 執行動畫 controller.forward(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'AnimateApp', theme: ThemeData( primaryColor: Colors.blue ), home: Scaffold( appBar: AppBar( title: Text('AnimateApp'), ), body: Center( child: Container( decoration: BoxDecoration( color: animation.value ), margin: EdgeInsets.symmetric(vertical: 10.0), height: 200.0, width: 200.0, ), // child: Container( // // 獲取動畫的值賦給 widget 的寬高 // width: animation.value, // height: animation.value, // decoration: BoxDecoration( // color: Colors.redAccent // ), // ), ) ) ); } @override void dispose() { // 資源釋放 controller.dispose(); super.dispose(); } }