Widgetの背景色を繰り返し点滅させるアニメーションを導入してみましょう。
これはAnimationController
を使い、Transition系のWidgetを追加することで実現可能です。
まず、コード全体を掲載します。
import 'package:flutter/material.dart';void main() => runApp(const MyApp());class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override _MyAppState createState() => _MyAppState();}class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin { late AnimationController _animationController; final DecorationTween _decorationTween = DecorationTween( begin: const BoxDecoration( color: Colors.blue, ), end: BoxDecoration( color: Colors.blue.shade100, ), ); @override void initState() { _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 3000), )..repeat(reverse: true); super.initState(); } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: const Text('サンプル'), ), body: Center( child: DecoratedBoxTransition( decoration: _decorationTween.animate(_animationController), child: const SizedBox( width: 200, height: 200, child: Center( child: Text('demo'), ), ), ), ), floatingActionButton: FloatingActionButton( child: const Icon(Icons.play_arrow), onPressed: () { print('aa'); }, ), ), ); }}
アニメーションの状態を保持する必要があるため、今回はStatefulWidgetを使います。
最初はアニメーションに必要な変数たちを準備します。
以下のコードを見てください。
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin { late AnimationController _animationController; final DecorationTween _decorationTween = DecorationTween( begin: const BoxDecoration( color: Colors.blue, ), end: BoxDecoration( color: Colors.blue.shade100, ), );
まず、12行目でクラスの定義を開始しますが、SingleTickerProviderStateMixin
を組み込んでいます。
これによりこのクラスの中でアニメーションを取り扱うことが可能になります。
そしてAnimationController
を状態として保持できるように_animationController
変数を用意しています。
15行目から始まるDecorationTween
は今回のアニメーションの内容です。begin:
にアニメーション開始時の状態を設定します。逆にend:
は終了時の状態ですね。
今回は青色から薄い青に変化していくように設定しました。
そして、_animationController
を初期化する処理が必要です。
以下のコードを見てください。
@override void initState() { _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 3000), )..repeat(reverse: true); super.initState(); } @override void dispose() { _animationController.dispose(); super.dispose(); }
initState
で_animationController
の初期化処理をしています。duration:
では再生スピードを指定しますが、今回は3秒にしています。
先ほど15行目で指定したアニメーションを3秒の時間をかけて再生することになります。begin:
の状態からend:
の状態に3秒間で変化していきます。
29行目でrepeat(reverse: true)
としています。
これにより、アニメーションは繰り返し再生されるようになります。reverse: true
にすると、繰り返し方が変わり、再生と逆再生を交互に行うようになります。
今回は背景色をシームレスに点滅させたいため、reverse: true
にしています。
35行目はおまじないですね。インスタンスが破棄されるときに_animationController
も破棄しています。
最後にアニメーションを仕掛けるところを指定します。
以下のコードを見てください。
body: Center( child: DecoratedBoxTransition( decoration: _decorationTween.animate(_animationController), child: const SizedBox( width: 200, height: 200, child: Center( child: Text('demo'), ), ), ), ),
アニメーションを追加する対象は50行目のSizedBox
以下になります。
対象を48行目のようにDecorateBoxTransition
で囲みます。
このとき、49行目のように15行目で定義したアニメーションを紐つけてあげることで、指定したアニメーションが適用されます。
あとはビルドをすると以下のコードのように点滅のアニメーションが再生されるでしょう。
*「Run」を押すと実行できます。
さて、今はアプリが起動した時点でアニメーションが再生されました。
ユーザーが任意の操作をしたタイミングで点滅のアニメーションを追加するにはどうしたらいいでしょうか?
まず、以下のようにinitState
で実行していたrepeat(reverse: true)
を取り除きます。
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 3000),
);
これで勝手にアニメーションが再生されることはなくなりました。
次にfloatingActionButton
を押した時にアニメーションが再生されるようにしてみます。
floatingActionButton: FloatingActionButton(
child: Icon(_animationController.isAnimating
? Icons.pause
: Icons.play_arrow),
onPressed: () {
setState(() {
if (_animationController.isAnimating) {
_animationController.stop();
} else {
_animationController.repeat(reverse: true);
}
});
},
),
onPressed:
のところにアニメーションの制御を追加しています。_animationController.isAnimating
がtrue
のときはアニメーション再生中です。
そのときはアニメーションをストップするようにしました。false
のとき(初回含む)は逆にアニメーションを再生しないといけません。
ここで、先ほど25行目からはじまるinitState
で取り除いたrepeat(reverse: true)
を追加すればOKです。
こうすれば任意のタイミングで繰り返しのアニメーションを有効化・無効化が可能になります。
以下はボタンを追加した場合のサンプルです。
*「Run」を押すと実行できます。