Skip to content

ElevatedButtonの背景色とスタイル設定

FlutterのElevatedButtonの背景色を変更する際に発生する一般的なエラーとその解決方法について解説します。

問題の概要

ElevatedButtonの背景色を関数経由で変更しようとした際に、以下のようなエラーが発生することがあります:

type '_MaterialStatePropertyAll' is not a subtype of type 'MaterialStateProperty<Color?>?'

このエラーは、MaterialStatePropertyの型が正しく設定されていない場合に発生します。

ソリューション

方法1: styleFromを使用する(推奨)

Flutter 3.1.0以降では、ElevatedButton.styleFromを使用するのが最も簡単で安全な方法です:

dart
ElevatedButton(
  onPressed: () {},
  child: Text('ボタン'),
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.red,      // 背景色
    foregroundColor: Colors.white,    // 文字色
    elevation: 5,                     // 影の高さ
    padding: EdgeInsets.all(16),      // パディング
  ),
)

TIP

styleFromメソッドは、ボタンの基本的なスタイル設定に最適で、コードが簡潔で読みやすくなります。

方法2: ButtonStyleとMaterialStatePropertyを使用する

より詳細なカスタマイズが必要な場合は、ButtonStyleMaterialStatePropertyを直接使用します:

dart
ElevatedButton(
  onPressed: () {},
  child: Text('ボタン'),
  style: ButtonStyle(
    backgroundColor: MaterialStateProperty.all<Color>(Colors.red),
    foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
    padding: MaterialStateProperty.all<EdgeInsets>(EdgeInsets.all(16)),
  ),
)

方法3: 状態に応じた色変更

ボタンの状態(押されたとき、ホバー時など)に応じて色を変更する場合は、MaterialStateProperty.resolveWithを使用します:

dart
ElevatedButton(
  onPressed: () {},
  child: Text('状態に応じて色が変わるボタン'),
  style: ButtonStyle(
    backgroundColor: MaterialStateProperty.resolveWith<Color>(
      (Set<MaterialState> states) {
        if (states.contains(MaterialState.pressed)) {
          return Colors.green; // 押されたときの色
        } else if (states.contains(MaterialState.hovered)) {
          return Colors.blue; // ホバー時の色
        }
        return Colors.red; // デフォルトの色
      },
    ),
  ),
)

元のコードの修正例

質問の元のコードを修正すると以下のようになります:

dart
void playSound(int soundNumber) {
  final player = AudioCache();
  player.play('note$soundNumber.wav');
}

Expanded buildPlayButton({Color color, int soundNumber}) {
  return Expanded(
    child: ElevatedButton(
      onPressed: () {
        playSound(soundNumber);
      },
      style: ElevatedButton.styleFrom(
        backgroundColor: color,
      ),
      child: Text('ノート $soundNumber'),
    ),
  );
}

呼び出し側:

dart
Widget build(BuildContext context) {
  return Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: <Widget>[
      buildPlayButton(color: Colors.red, soundNumber: 1),
      buildPlayButton(color: Colors.orange, soundNumber: 2),
      buildPlayButton(color: Colors.yellow, soundNumber: 3),
      buildPlayButton(color: Colors.green, soundNumber: 4),
      buildPlayButton(color: Colors.blue, soundNumber: 5),
      buildPlayButton(color: Colors.indigo, soundNumber: 6),
      buildPlayButton(color: Colors.purple, soundNumber: 7),
    ],
  );
}

バージョン対応について

WARNING

Flutter 3.1.0以前と以降でプロパティ名が変更されている点に注意してください:

  • 3.1.0以前: primary(背景色), onPrimary(文字色)
  • 3.1.0以降: backgroundColor, foregroundColor

古いコードを扱う場合は、この違いに注意が必要です。

追加のスタイル設定

ボタンの形や枠線もカスタマイズできます:

dart
ElevatedButton(
  onPressed: () {},
  child: Text('カスタムボタン'),
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
    foregroundColor: Colors.white,
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(20), // 角丸
    ),
    side: BorderSide(
      color: Colors.black, // 枠線の色
      width: 1,            // 枠線の太さ
    ),
  ),
)

まとめ

ElevatedButtonの背景色を変更するには:

  1. 簡易な方法: ElevatedButton.styleFrom()を使用
  2. 詳細なカスタマイズ: ButtonStyleMaterialStatePropertyを使用
  3. 状態に応じた変更: MaterialStateProperty.resolveWith()を使用

Flutterのバージョンに応じて適切なプロパティ名を使用し、型の不一致エラーを避けるようにしましょう。