LoginSignup
20
8

More than 3 years have passed since last update.

【Flutter】MaterialStatePropertyってなんだ?

Last updated at Posted at 2020-12-12

はじめに

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の非活性な状態を表します。

スクリーンショット 2020-12-12 14.08.37.png

MaterialStateのその他の状態については公式ドキュメントをご参照ください。

MaterialStatePropertyの使い方

MaterialStatePropertyではMaterialStateによって値を変えることができます。
ここではMaterialStatePropertyの使い方を下記の2パターンに分けて紹介します。

  • 全てのMaterialStateで同じ値を設定したい
  • MaterialStateによって設定する値を変えたい

全てのMaterialStateで同じ値を設定したい

冒頭で挙げたElevatedButtonに背景色をつけたいというケースでは、ElevatedButtonがどんな状態であれ指定したColorの背景色になっていれば良いというケースでした。
このような全てのMaterialStateで同じ値を設定したいというケースでは、MaterialStateProperty.allメソッドを使います。

MaterialStateProperty.allメソッドを使ってElevatedButtonに背景色を設定した実行結果とコードはこちらです。

スクリーンショット 2020-12-12 15.08.39.png

  @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メソッドを使います。

例えばボタンが押されている状態とそうでない状態で背景色を変えたい場合は下記のように実装します。

ezgif.com-gif-maker.gif

  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メソッドがある

以上です。

20
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
8