🤫
Flutterでコンストラクターを使う
どんなふうに使う?
Dartの学習をしたときに、コンストラクターを勉強したけどFlutterのWidgetではどう使えばいいのかイメージがわかなかった?
やることは、単純で外部の値をクラスに渡すのに使います。
分かりやすい例を出すと、ボタンのWidgetを切り分けてコンポーネント化して、色とサイズを変更できるものを作って学んでみました。
よくある例が、ボタンを一個ずつ追加していって色やサイズを変える方法。でもこれは何だか冗長ですね。
冗長とは、重複していたり不必要に長かったりして無駄が多いこと。
はい、私のことです😅
これをいくつも書いて、styleを追加していく。
ElevatedButton(onPressed: (){}, child: Text('Button')),
でも使いませたら便利じゃない?
VScodeでWidgetを切り分けるときは、ElevatedButtonを選択した状態で、command + . を押して、Widgetを切り分ける操作ができます。
ソースコードはこんな感じです。でもこれだけだと物足りない。
なので、外部から値を渡してボタンの色と名前を変更できるようにします。
class ButtonComponent extends StatelessWidget {
const ButtonComponent({
Key? key,
}) : super(key: key);
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.black,
fixedSize: Size(100, 50)),
onPressed: () {},
child: Text('Button'));
}
}
変数を定義して、コンストラクターを追加すると引数を渡せるようになります。今回だと、渡しているのは文字に見えますが、変数の型は、Colorにしないと、エラー吐いちゃいます!
マウスをホバーすると、backgroundColorの型が確認できるので、Colorを変数の型に指定しましょう。
変数を追加すると、エラーがコンストラクターの箇所で出てくるので、コードの保管機能で追加します。
class BaseButton extends StatelessWidget {
const BaseButton({
Key? key,
required this.background,
required this.foreground,
required this.buttonName,
}) : super(key: key);
final Color background;// ボタンの背景色.
final Color foreground;// ボタンの文字色.
final String buttonName;// ボタンの名前.
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: background,// 変数を使用する.
foregroundColor: foreground,// 変数を使用する.
fixedSize: Size(100, 50)),
onPressed: () {},
child: Text(buttonName)// 変数を使用する.
);
}
}
全体のコード
main.dart
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: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const ButtonApp(),
);
}
}
class ButtonApp extends StatelessWidget {
const ButtonApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Button'),
),
body: Center(
child: Column(children: [
SizedBox(height: 20),
ButtonComponent(),
SizedBox(height: 20),
BaseButton(
background: Colors.blue,
foreground: Colors.amber,
buttonName: "Button1",
),
SizedBox(height: 20),
BaseButton(
background: Colors.amber,
foreground: Colors.black,
buttonName: "Button2",
)
]),
),
);
}
}
class ButtonComponent extends StatelessWidget {
const ButtonComponent({
Key? key,
}) : super(key: key);
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.black,
fixedSize: Size(100, 50)),
onPressed: () {},
child: Text('Button'));
}
}
class BaseButton extends StatelessWidget {
const BaseButton({
Key? key,
required this.background,
required this.foreground, required this.buttonName,
}) : super(key: key);
final Color background;// ボタンの背景色.
final Color foreground;// ボタンの文字色.
final String buttonName;// ボタンの名前.
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: background,// 変数を使用する.
foregroundColor: foreground,// 変数を使用する.
fixedSize: Size(100, 50)),
onPressed: () {},
child: Text(buttonName)// 変数を使用する.
);
}
}
最後に
パーツは使いませるように、コンポーネント化しないと無駄なコードがどんどん増えていって肥大化する。
以前は、これを解決できてなかったので、何度も同じWidgetを書いておりました😅
Discussion