はじめに
MaterialStatePropertyとは何なのか疑問に思ったのは、**ElevatedButton**に背景色をつける実装をしようとしている時でした。
ElevatedButtonには**ButtonStyleを設定でき、このButtonStyleのプロパティbackgroundColor**にColorの値を設定してあげれば背景色をつけられると思っていたのですが、backgroundColorの型はColorではなく、MaterialStateProperty<Color>
でした。
このMaterialStateProperty
ってなんだ?
動作環境
- Flutter 1.22.4
- Dart 2.10.4
MaterialStatePropertyとは
結論から書くと、MaterialStatePropertyは、MaterialStateの状態によって決まる値のことです。
例えば上記で挙げたButtonStyleのbackgroundColorの型は、MaterialStateProperty<Color>
ですが、これはMaterialStateの状態によってColorの値が決まるということです。
MaterialStatePropertyの値の型はジェネリクスを使って動的に決まるようになっています。
MaterialStateとは
MaterialStateはユーザーの入力によって変化するMaterialWidgetの状態を表します。
MaterialStateはenumで定義されており、例えばMaterialState.disabled
はWidgetの非活性な状態を表します。
MaterialStateのその他の状態については公式ドキュメントをご参照ください。
MaterialStatePropertyの使い方
MaterialStatePropertyではMaterialStateによって値を変えることができます。
ここではMaterialStatePropertyの使い方を下記の2パターンに分けて紹介します。
- 全てのMaterialStateで同じ値を設定したい
- MaterialStateによって設定する値を変えたい
全てのMaterialStateで同じ値を設定したい
冒頭で挙げたElevatedButtonに背景色をつけたいというケースでは、ElevatedButtonがどんな状態であれ指定したColorの背景色になっていれば良いというケースでした。
このような全てのMaterialStateで同じ値を設定したいというケースでは、MaterialStateProperty.allメソッドを使います。
MaterialStateProperty.allメソッドを使ってElevatedButtonに背景色を設定した実行結果とコードはこちらです。
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.red),
),
child: Text('TextButton'),
onPressed: () {},
);
}
どんなMaterialStateであれColors.redが設定されるので、ボタンを押下するなどで状態を変更しても背景色は変わりません。
MaterialStateによって設定する値を変えたい
MaterialStateによって設定する値を変えたい場合は、MaterialStateProperty.resolveWithメソッドを使います。
例えばボタンが押されている状態とそうでない状態で背景色を変えたい場合は下記のように実装します。
Color backgroundColor(Set<MaterialState> states) {
// 場合分けする状態のリストを定義
const Set<MaterialState> interactiveStates = <MaterialState>{
MaterialState.pressed,
};
if (states.any(interactiveStates.contains)) {
return Colors.blue;
}
return Colors.red;
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.resolveWith(this.backgroundColor),
),
child: Text('TextButton'),
onPressed: () {},
);
}
MaterialStateProperty.resolveWithメソッドでは引数に、MaterialStateによって値を返すメソッドを渡しています。
そしてそのメソッド(backgroundColorメソッド)では、ボタンが押された状態(MaterialState.pressed)とそうでない時でreturnする背景色を変えています。
所感
インタラクティブなWidgetのプロパティがMaterialStatePropertyで統一されればより汎用的にレイアウトを実装できるので良いと思いました。
まとめ
- MaterialStatePropertyとはMaterialStateによって決まる値
- MaterialStateとはユーザーの入力によって変化するMaterialWidgetの状態(ボタンが押された、非活性になった、など)
- MaterialStatePropertyでは全ての状態で同じ値にするallメソッドと、状態によって値を変更するresolveWithメソッドがある
以上です。