今回はStateによってスタイルが変化する場合の移行について記述したいと思います。
前回の記事では、styleプロパティにほぼコピペするだけで移行できましたが、今回はMaterialStatePropertyというクラスを利用します。
自社アプリでは、ラジオボタンのように難易度を選択するボタンが用意されていますが、インストール時、中級と上級のボタンは無効になっていて、下の級をクリアしないと有効化されません。コードは以下のようになっています。
RaisedButton(
onPressed: unlocked ? callback : null,
disabledColor: Colors.grey,
disabledTextColor: Colors.white,
disabledElevation: 2,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
textColor: Colors.white,
color: buttonColor,
padding: EdgeInsets.symmetric(vertical: fontSize / 3),
child: buttonStack,
),
前回同様、RaisedButtonをElevatedButtonに変更して、廃止されたプロパティをコメントアウトします。
ElevatedButton(
onPressed: unlocked ? callback : null,
// disabledColor: Colors.grey,
// disabledTextColor: Colors.white,
// disabledElevation: 2,
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
// textColor: Colors.white,
// color: buttonColor,
// padding: EdgeInsets.symmetric(vertical: fontSize / 3),
child: buttonStack,
),
ホットリロードすると、新しいデフォルトのボタンのスタイルで表示されます。無効化されているボタンについては半透明になっています。
参考用のドキュメントを確認すると、無効化(disabled)の状態のスタイルをカスタマイズする場合は、MaterialStatePropertyを使う必要があると記載があります。これにより、他のプロパティもMaterialStatePropertyで書くことになります。
無効化されているときの背景色(disabledColor)をColors.greyにするためには以下のようにコードを追加します。
ElevatedButton(
onPressed: unlocked ? callback : null,
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) return Colors.grey;
return buttonColor; // buttonColorはデフォルトカラーです。
},
),
),
// disabledColor: Colors.grey,
// disabledTextColor: Colors.white,
// disabledElevation: 2,
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
// textColor: Colors.white,
// color: buttonColor,
// padding: EdgeInsets.symmetric(vertical: fontSize / 3),
child: buttonStack,
),
ホットリロードすると、無効化されたボタンがデフォルトの半透明がなくなり、Colors.greyが適用されていることがわかります。
この形式を踏襲して、他のプロパティもMaterialStatePropertyを使って適用していくとこうなります。
ElevatedButton(
onPressed: unlocked ? callback : null,
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) return Colors.grey;
return buttonColor; // buttonColorはデフォルトカラーです。
},
),
foregroundColor: MaterialStateProperty.resolveWith<Color>(
(states) => Colors.white,
),
elevation: MaterialStateProperty.resolveWith(
(states) => 2,
),
shape: MaterialStateProperty.resolveWith(
(states) => RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
textStyle: MaterialStateProperty.resolveWith(
(states) => TextStyle(color: Colors.white),
),
padding: MaterialStateProperty.resolveWith(
(states) => EdgeInsets.symmetric(vertical: fontSize / 3),
),
),
child: buttonStack,
),
MaterialStatePropertyを挟むことで、冗長になりますが、Stateによって変化しないプロパティに関しては、アロー関数で固定値を返せばよいだけです。
今回のようにアップデートすると、リファクタリングする機会にもなるので、勉強にもなりますね。