【Flutter入門】コンテナのプロパティをアニメーション化するランダムに
こんにちは、今回はflutter/cookbookに記載されている「Animate the properties of a container」を体感します!
面白い機能ですね〜
全体コード(立ち上げ時の初期コードにぶち込んでいます)
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'AnimatedContainer Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'AnimatedContainer Demo'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key, required this.title});
final String title;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: const Center(child: AnimatedContainerApp()),
);
}
}
class AnimatedContainerApp extends StatefulWidget {
const AnimatedContainerApp({super.key});
State<AnimatedContainerApp> createState() => _AnimatedContainerAppState();
}
class _AnimatedContainerAppState extends State<AnimatedContainerApp> {
double _width = 100;
double _height = 100;
Color _color = Colors.green;
BorderRadiusGeometry _boderRadius = BorderRadius.circular(8);
void _changeProperties() {
final random = Random();
setState(() {
_width = random.nextInt(200).toDouble() + 50;
_height = random.nextInt(200).toDouble() + 50;
_color = Color.fromRGBO(
random.nextInt(256),
random.nextInt(256),
random.nextInt(256),
1,
);
_boderRadius = BorderRadius.circular(random.nextInt(100).toDouble());
});
}
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedContainer(
width: _width,
height: _height,
decoration: BoxDecoration(color: _color, borderRadius: _boderRadius),
duration: const Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _changeProperties,
child: const Text('Change Animation'),
),
],
);
}
}
解説のようなメモ
全体構造と目的
・このアプリは「ボタンを押すとAnimatedContainerのサイズ・色・角丸がランダムに変化してアニメーションする」というデモ
・StatefulWidgetを使って状態管理とアニメーションを実現していることに注目する。
Widgetツリー構造
・MyApp/ flutterアプリのエントリーポイント。MaterialAppでアプリ全体のテーマとhomeを設定
・MyHomePage/Scaffoldを使ってタイトル付きのページを作成。
・AnimatedContainerApp/状態管理を持ったStatefulWidget、ここがアニメーションのロジック部分。
StatefulWidgetの使い方
・AnimatedContainerApp と _AnimatedContainerAppState
.Stateクラスに_width,_height,_color,_boderRadiusといった状態(プロパティ)を持っていることがポイント。
・_changeProperitsメソッドでsetstateを読んで値を変更→再描写トリガーにしている。
AnimatedContainer の役割
.AnimatedContainerはプロパティが変わると、自動でスムーズにアニメーションしてくれる便利なウィジェット。
・durationとcurveでアニメーションの速度や動き方を設定している。
・BoxDevotationを受かってcolorとboderRadiusを同時に変化させている
Randomによるプロパティの変更
・Random()を使って幅・高さ・色・角丸をランダムに変化させているところ
・setState()で変更を反映それに伴ってアニメーションが実行される
その他メモ:
【Randomインスタンス】
final random = Random();
Dart標準ライブラリ dart:math から Random() を使い、乱数を生成する準備。
【幅・高さのランダム化】
_width = random.nextInt(200).toDouble() + 50;
_height = random.nextInt(200).toDouble() + 50;
random.nextInt(200) で 0~199 の整数値を作り、+50 することで最終的に 50 ~ 249 の範囲に調整している。
toDouble() で double 型に変換して、 AnimatedContainer に渡せるようにしている。
【色のランダム化】
_color = Color.fromRGBO(
random.nextInt(256),
random.nextInt(256),
random.nextInt(256),
1,
);
RGB 各要素を 0~255 からランダムに生成。
最後の 1 は透明度(alpha)で、完全不透明を指定。
【角丸のランダム化】
_boderRadius = BorderRadius.circular(random.nextInt(100).toDouble());
半径を 0 ~ 99 からランダムに決めて角丸を変化。
数値が大きいほど丸くなる。
※ ここはタイプミスで _boderRadius になっているけど、本来 borderRadius が正しい。
【UI変更トリガー】
これらの変更を setState() 内で行うことで、 AnimatedContainer が自動でアニメーションを開始する仕組みになっている。
Discussion