<

新しいボタンとボタンのテーマ

まとめ

基本的なマテリアル ボタン ウィジェットとテーマの新しいセットが追加されました flutterに。元のクラスは廃止されました。 最終的には削除されます。全体的な目標は、ボタンを増やすことです。 柔軟で、コンストラクター パラメーターまたは テーマ。

FlatButtonRaisedButtonOutlineButtonウィジェットは と取り換えるTextButtonElevatedButton、 とOutlinedButtonそれぞれ。新しいボタン クラスにはそれぞれ独自のテーマがあります。TextButtonThemeElevatedButtonTheme、 とOutlinedButtonTheme。オリジナルButtonThemeクラスはもうありません 使用済み。ボタンの外観は、ButtonStyleウィジェットパラメータの大規模なセットの代わりにオブジェクトを使用し、 プロパティ。これは、外観の様子とほぼ同等です。 のテキストは、TextStyle物体。新しいボタンのテーマ も設定されていますButtonStyle物体。あButtonStyleは それ自体は単なる視覚プロパティのコレクションです。これらの多くは プロパティは次のように定義されますMaterialStateProperty、つまり、 それらの値はボタンの状態によって異なります。

コンテクスト

既存のボタン クラスとそのテーマを進化させようとするのではなく、 新しい代替ボタン ウィジェットを導入し、 テーマ。下位互換性から解放されるだけでなく、 既存のクラスをインプレースで進化させるには、次のような迷路が伴います。 新しい名前は、Flutter バックアップをマテリアル デザイン仕様と同期します。 これにより、ボタン コンポーネントの新しい名前が使用されます。

古いウィジェット 古いテーマ 新しいウィジェット 新しいテーマ
FlatButton ButtonTheme TextButton TextButtonTheme
RaisedButton ButtonTheme ElevatedButton ElevatedButtonTheme
OutlineButton ButtonTheme OutlinedButton OutlinedButtonTheme

新しいテーマは、Flutter が採用した「正規化された」パターンに従っています 約 1 年前に新しいマテリアル ウィジェットを作成しました。テーマのプロパティとウィジェット コンストラクターのパラメーターはデフォルトでは null です。 null 以外のテーマのプロパティ ウィジェットパラメータはコンポーネントのデフォルトのオーバーライドを指定します 価値。デフォルト値の実装と文書化が唯一の方法です。 ボタンコンポーネントウィジェットの責任。デフォルト それら自体は主にテーマ全体の colorScheme に基づいており、 テキストのテーマ。

新しいボタンは一致しているため、視覚的には少し異なって見えます。 現在のマテリアル デザイン仕様とその色が テーマ全体の ColorScheme に関して構成されます。がある その他、パディング、丸い角の半径、および ホバー/フォーカス/押されたフィードバック。

多くのアプリケーションは新しいクラス名をそのまま置き換えることができます。 古い人たちのために。ゴールデン イメージ テストまたはボタンを備えたアプリ 外観はコンストラクター パラメーターまたは オリジナルButtonTheme移行ガイドと 続いて紹介資料。

API の変更: 個々のスタイル プロパティの代わりに ButtonStyle

単純な使用例を除き、新しいボタン クラスの API は次のとおりです。 古いクラスとは互換性がありません。新しいものの視覚的属性 ボタンとテーマは 1 つで構成されますButtonStyle物体、 のやり方と似ていますTextFieldまたはTextウィジェットは、TextStyle物体。ほとんどButtonStyleプロパティは次のように定義されますMaterialStateProperty、単一のプロパティで表すことができるように ボタンが押された/フォーカスされている/ホバーされているなどに応じて異なる値 州。

ボタンのButtonStyleボタンの視覚的なプロパティを定義しません。 ボタンのデフォルトの視覚プロパティのオーバーライドを定義します。 ここで、デフォルトのプロパティはボタン ウィジェットによって計算されます。 自体。たとえば、TextButtonのデフォルトの前景 すべての状態の (テキスト/アイコン) 色を指定するには、次のように記述できます。

TextButton(
  style: ButtonStyle(
    foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
  ),
  onPressed: () { },
  child: Text('TextButton'),
)

この種のオーバーライドは一般的です。ただし、多くの場合、 テキストボタンが使用するオーバーレイカラーのオーバーライドが必要です ホバー/フォーカス/押された状態を示します。これは次の方法で実行できます 追加overlayColorの財産ButtonStyle

TextButton(
  style: ButtonStyle(
    foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
    overlayColor: MaterialStateProperty.resolveWith<Color?>(
      (Set<MaterialState> states) {
        if (states.contains(MaterialState.hovered))
          return Colors.blue.withOpacity(0.04);
        if (states.contains(MaterialState.focused) ||
            states.contains(MaterialState.pressed))
          return Colors.blue.withOpacity(0.12);
        return null; // Defer to the widget's default.
      },
    ),
  ),
  onPressed: () { },
  child: Text('TextButton')
)

MaterialStatePropertyの値を返すだけで済みます。 デフォルトをオーバーライドする必要がある色。 null を返した場合、 代わりにウィジェットのデフォルトが使用されます。たとえば、単にオーバーライドするには テキストボタンのフォーカスオーバーレイの色:

TextButton(
  style: ButtonStyle(
    overlayColor: MaterialStateProperty.resolveWith<Color?>(
      (Set<MaterialState> states) {
        if (states.contains(MaterialState.focused))
          return Colors.red;
        return null; // Defer to the widget's default.
      }
    ),
  ),
  onPressed: () { },
  child: Text('TextButton'),
)

styleFrom()ButtonStyle ユーティリティのメソッド

マテリアル デザイン仕様では、ボタンの前景色とオーバーレイの色が定義されています。 配色の原色の用語。原色は、 ボタンの状態に応じて、異なる不透明度でレンダリングされます。に すべてのプロパティを含むボタン スタイルの作成を簡素化します。 配色の色に依存するボタン クラスには、 を構築する静的 styleFrom() メソッドButtonStyle単純なことから を含む一連の値ColorSchemeそれは色に依存します。

この例では、次のように前景色をオーバーライドするボタンを作成します。 指定された原色とそのオーバーレイ カラーを使用します。 マテリアル デザイン仕様の不透明度。

TextButton(
  style: TextButton.styleFrom(
    primary: Colors.blue,
  ),
  onPressed: () { },
  child: Text('TextButton'),
)

TextButtonドキュメントには、次の前景色が示されています。 ボタンが無効になるかどうかは、配色に基づいていますonSurface色。これをオーバーライドするには、styleFrom() を使用します。

TextButton(
  style: TextButton.styleFrom(
    primary: Colors.blue,
    onSurface: Colors.red,
  ),
  onPressed: null,
  child: Text('TextButton'),
)

の使用styleFrom()メソッドは、ButtonStyleマテリアル デザインを作成しようとしている場合 変化。最も柔軟なアプローチは、ButtonStyle直接、一緒にMaterialStateProperty州の価値観 上書きしたい外観。

ButtonStyle のデフォルト

新しいボタンクラスのようなウィジェット計算するデフォルト値 全体的なテーマに基づいて、colorSchemetextThemeとしても ボタンの現在の状態。いくつかのケースでは、次のようなことも考慮されます。 全体的なテーマの配色は明るいか暗いかです。各ボタンには 必要に応じてデフォルトのスタイルを計算する保護されたメソッド。それでも アプリはこのメソッドを直接呼び出すことはありません。その API ドキュメントですべての内容が説明されています デフォルトは次のとおりです。ボタンまたはボタンのテーマが指定している場合ButtonStyle、ボタン スタイルの null 以外のプロパティのみが 計算されたデフォルト。ボタンのstyleパラメータはnull以外をオーバーライドします 対応するボタンのテーマで指定されたプロパティ。たとえば、foregroundColorの財産TextButtonのスタイルは null ではありません。 の同じプロパティをオーバーライドします。TextButonThemeのスタイル。

前に説明したように、各ボタン クラスには静的メソッドが含まれています。 呼ばれたstyleFromこれは、単純なセットから ButtonStyle を構築します。 を含む値ColorSchemeそれは色に依存します。多くの共通点 ケース、使用styleFromワンオフのものを作成するButtonStyleそれか デフォルトをオーバーライドするのが最も簡単です。これは特に次の場合に当てはまります。 カスタム スタイルの目的は、配色の 1 つをオーバーライドすることです。 色などprimaryまたonPrimaryデフォルトのスタイルが依存すること の上。他のケースでは、ButtonStyle物体 直接。そうすることで、視覚的な価値を制御できるようになります。 ボタンのすべての可能な状態の色などのプロパティ - 押された、ホバーされた、無効になっている、フォーカスされているなど。

移行ガイド

次の情報を使用して、ボタンを 新しいAPI。

元のボタンのビジュアルを復元する

多くの場合、古いボタン クラスから切り替えるだけで済みます。 新しいものへ。これは、サイズや形状に小さな変化があることを前提としています。 そしておそらく色の大きな変化は心配ありません。

このような場合に元のボタンの外観を維持するには、次のようにします。 オリジナルと同じくらい一致するボタン スタイルを定義します。 好き。たとえば、次のスタイルはTextButton見て デフォルトのようにFlatButton:

final ButtonStyle flatButtonStyle = TextButton.styleFrom(
  primary: Colors.black87,
  minimumSize: Size(88, 36),
  padding: EdgeInsets.symmetric(horizontal: 16),
  shape: const RoundedRectangleBorder(
    borderRadius: BorderRadius.all(Radius.circular(2)),
  ),
);

TextButton(
  style: flatButtonStyle,
  onPressed: () { },
  child: Text('Looks like a FlatButton'),
)

同様に、ElevatedButtonデフォルトのように見えるRaisedButton:

final ButtonStyle raisedButtonStyle = ElevatedButton.styleFrom(
  onPrimary: Colors.black87,
  primary: Colors.grey[300],
  minimumSize: Size(88, 36),
  padding: EdgeInsets.symmetric(horizontal: 16),
  shape: const RoundedRectangleBorder(
    borderRadius: BorderRadius.all(Radius.circular(2)),
  ),
);
ElevatedButton(
  style: raisedButtonStyle,
  onPressed: () { },
  child: Text('Looks like a RaisedButton'),
)

OutlineButtonのためのスタイルOutlinedButtonもう少しです 輪郭の色が原色に変わるので複雑 ボタンを押したとき。アウトラインの外観は、BorderSideそして、あなたはMaterialStateProperty押されたものを定義するには 輪郭の色:

final ButtonStyle outlineButtonStyle = OutlinedButton.styleFrom(
  primary: Colors.black87,
  minimumSize: Size(88, 36),
  padding: EdgeInsets.symmetric(horizontal: 16),
  shape: const RoundedRectangleBorder(
    borderRadius: BorderRadius.all(Radius.circular(2)),
  ),
).copyWith(
  side: MaterialStateProperty.resolveWith<BorderSide>(
    (Set<MaterialState> states) {
      if (states.contains(MaterialState.pressed))
        return BorderSide(
          color: Theme.of(context).colorScheme.primary,
          width: 1,
        );
      return null; // Defer to the widget's default.
    },
  ),
);

OutlinedButton(
  style: outlineButtonStyle,
  onPressed: () { },
  child: Text('Looks like an OutlineButton'),
)

全体を通してボタンの外観をデフォルトに戻すには、 アプリケーションでは、新しいボタンのテーマを設定できます。 アプリケーションのテーマ:

MaterialApp(
  theme: ThemeData.from(colorScheme: ColorScheme.light()).copyWith(
    textButtonTheme: TextButtonThemeData(style: flatButtonStyle),
    elevatedButtonTheme: ElevatedButtonThemeData(style: raisedButtonStyle),
    outlinedButtonTheme: OutlinedButtonThemeData(style: outlineButtonStyle),
  ),
)

一部のボタンの外観をデフォルトに戻すには、 ウィジェットのサブツリーをラップできるアプリケーションTextButtonThemeElevatedButtonTheme、 またOutlinedButtonTheme。例えば:

TextButtonTheme(
  data: TextButtonThemeData(style: flatButtonStyle),
  child: myWidgetSubtree,
)

カスタムカラーを使用したボタンの移行

次のセクションでは、次の使用方法について説明します。FlatButtonRaisedButton、 とOutlineButton色のパラメータ:

textColor
disabledTextColor
color
disabledColor
focusColor
hoverColor
highlightColor*
splashColor

新しいボタン クラスは個別のハイライト色をサポートしていません それはもはやマテリアル デザインの一部ではないからです。

カスタムの前景色と背景色を使用したボタンの移行

元のボタン クラスの 2 つの一般的なカスタマイズは、 の前景色FlatButton、またはカスタムの前景と背景 の色RaisedButton。新しいものでも同じ結果が得られます ボタンのクラスは単純です。

FlatButton(
  textColor: Colors.red, // foreground
  onPressed: () { },
  child: Text('FlatButton with custom foreground/background'),
)

TextButton(
  style: TextButton.styleFrom(
    primary: Colors.red, // foreground
  ),
  onPressed: () { },
  child: Text('TextButton with custom foreground'),
)

この場合、TextButtonの前景色 (テキスト/アイコン) の色と ホバー/フォーカス/プレスされたオーバーレイの色は、Colors.red。デフォルトでは、TextButtonの背景の塗りつぶし色は 透明。

移行中RaisedButtonカスタムの前景色と背景色を使用:

RaisedButton(
  color: Colors.red, // background
  textColor: Colors.white, // foreground
  onPressed: () { },
  child: Text('RaisedButton with custom foreground/background'),
)

ElevatedButton(
  style: ElevatedButton.styleFrom(
    primary: Colors.red, // background
    onPrimary: Colors.white, // foreground
  ),
  onPressed: () { },
  child: Text('ElevatedButton with custom foreground/background'),
)

この場合、ボタンで使用される配色の原色は次のとおりです。 に対して逆転したTextButton: プライマリはボタンの背景です 塗りつぶしの色とonPrimary前景色 (テキスト/アイコン) の色です。

カスタム オーバーレイ カラーを使用したボタンの移行

ボタンのデフォルトのフォーカス、ホバー、ハイライト、またはスプラッシュをオーバーライドする 色はあまり一般的ではありません。のFlatButtonRaisedButton、 とOutlineButtonクラスには、これらの状態依存の個別のパラメータがあります。 色。新しいTextButtonElevatedButton、 と0f89牛肉-f900-42d6-90d8-3ca29998a48fクラス 単一のものを使用するMaterialStateProperty<Color>代わりにパラメータを使用します。新しい ボタンを使用すると、すべての状態に依存する値を指定できます。 色、元のボタンは現在のものを指定することのみをサポートしていました 「overlayColor」と呼ばれます。

FlatButton(
  focusColor: Colors.red,
  hoverColor: Colors.green,
  splashColor: Colors.blue,
  onPressed: () { },
  child: Text('FlatButton with custom overlay colors'),
)

TextButton(
  style: ButtonStyle(
    overlayColor: MaterialStateProperty.resolveWith<Color?>(
      (Set<MaterialState> states) {
        if (states.contains(MaterialState.focused))
          return Colors.red;
        if (states.contains(MaterialState.hovered))
            return Colors.green;
        if (states.contains(MaterialState.pressed))
            return Colors.blue;
        return null; // Defer to the widget's default.
    }),
  ),
  onPressed: () { },
  child: Text('TextButton with custom overlay colors'),
)

新しいバージョンは、コンパクトさは劣るものの、より柔軟になっています。の中に 元のバージョンでは、さまざまな状態の優先順位は次のとおりです。 新しいバージョンでは、暗黙的 (文書化されていない) かつ修正されています。 明示的な。これらの色を頻繁に指定するアプリの場合、 最も簡単な移行パスは、1 つ以上を定義することですButtonStyles上記の例と一致し、style パラメータのみを使用するか、 3 つの色をカプセル化するステートレス ラッパー ウィジェットを定義します。 パラメーター。

カスタム無効色のボタンを移行する

比較的珍しいカスタマイズです。のFlatButtonRaisedButton、 とOutlineButtonクラスにはdisabledTextColordisabledColor背景と前景を定義するパラメータ ボタンが押されたときの色onPressedコールバックがnullです。

デフォルトでは、すべてのボタンにその配色が使用されます。onSurface色、 無効な前景色の不透明度 0.38。それだけElevatedButton不透明な背景色とそのデフォルト 値はonSurface不透明度0.12のカラー。したがって、多くの場合、 を使用できますstyleFrom無効な色をオーバーライドするメソッド:

RaisedButton(
  disabledColor: Colors.red.withOpacity(0.12),
  disabledTextColor: Colors.red.withOpacity(0.38),
  onPressed: null,
  child: Text('RaisedButton with custom disabled colors'),
),

ElevatedButton(
  style: ElevatedButton.styleFrom(onSurface: Colors.red),
  onPressed: null,
  child: Text('ElevatedButton with custom disabled colors'),
)

無効な色を完全に制御するには、ElevatedButtonのスタイルを明確に、MaterialStateProperties:

RaisedButton(
  disabledColor: Colors.red,
  disabledTextColor: Colors.blue,
  onPressed: null,
  child: Text('RaisedButton with custom disabled colors'),
)

ElevatedButton(
  style: ButtonStyle(
    backgroundColor: MaterialStateProperty.resolveWith<Color?>(
      (Set<MaterialState> states) {
        if (states.contains(MaterialState.disabled))
          return Colors.red;
        return null; // Defer to the widget's default.
    }),
    foregroundColor: MaterialStateProperty.resolveWith<Color?>(
      (Set<MaterialState> states) {
        if (states.contains(MaterialState.disabled))
          return Colors.blue;
        return null; // Defer to the widget's default.
    }),
  ),
  onPressed: null,
  child: Text('ElevatedButton with custom disabled colors'),
)

前のケースと同様に、新しいものを作成する明白な方法があります。 この移行が頻繁に発生するアプリでは、よりコンパクトなバージョンになります。

カスタム高さを使用したボタンの移行

こちらも比較的珍しいカスタマイズです。通常、のみElevatedButtons (元々はRaisedButtons) 標高の変化も含みます。比例する標高の場合 (マテリアル デザイン仕様に従って) ベースライン標高まで、 それらはすべて非常に簡単にオーバーライドできます。

デフォルトでは、無効になっているボタンの高さは 0 で、残りのボタンの高さは 0 です。 状態はベースライン 2 を基準にして定義されます。

disabled: 0
hovered or focused: baseline + 2
pressed: baseline + 6

したがって、移行するにはRaisedButtonすべての標高が 定義:

RaisedButton(
  elevation: 2,
  focusElevation: 4,
  hoverElevation: 4,
  highlightElevation: 8,
  disabledElevation: 0,
  onPressed: () { },
  child: Text('RaisedButton with custom elevations'),
)

ElevatedButton(
  style: ElevatedButton.styleFrom(elevation: 2),
  onPressed: () { },
  child: Text('ElevatedButton with custom elevations'),
)

押された高度のように、1 つの標高だけを任意にオーバーライドするには 標高:

RaisedButton(
  highlightElevation: 16,
  onPressed: () { },
  child: Text('RaisedButton with a custom elevation'),
)

ElevatedButton(
  style: ButtonStyle(
    elevation: MaterialStateProperty.resolveWith<double?>(
      (Set<MaterialState> states) {
        if (states.contains(MaterialState.pressed))
          return 16;
        return null;
      }),
  ),
  onPressed: () { },
  child: Text('ElevatedButton with a custom elevation'),
)

カスタムの形状と枠線を使用したボタンの移行

オリジナルFlatButtonRaisedButton、 とOutlineButtonクラスすべて ボタンの形状と その輪郭の様子。対応する新しいクラスとそのクラス テーマはボタンの形状とその境界線の指定をサポートしています 別に、一緒にfaeefb3-6e30-4a05-9e8e-603907e4e33eとBorderSide sideパラメーター。

この例では、元のOutlineButtonバージョンは同じを指定します ハイライトされた(押された)状態の境界線の色は、他の境界線と同様です 州。

OutlineButton(
  shape: StadiumBorder(),
  highlightedBorderColor: Colors.red,
  borderSide: BorderSide(
    width: 2,
    color: Colors.red
  ),
  onPressed: () { },
  child: Text('OutlineButton with custom shape and border'),
)

OutlinedButton(
  style: OutlinedButton.styleFrom(
    shape: StadiumBorder(),
    side: BorderSide(
      width: 2,
      color: Colors.red
    ),
  ),
  onPressed: () { },
  child: Text('OutlinedButton with custom shape and border'),
)

新しいもののほとんどは、OutlinedButtonウィジェットのスタイルパラメータ(以下を含む) その形状と境界線は次のように指定できます。MaterialStatePropertyつまり、値に応じて異なる値を持つことができます。 ボタンの状態について。別の境界線の色を指定するには、 ボタンが押された場合は、次の手順を実行します。

OutlineButton(
  shape: StadiumBorder(),
  highlightedBorderColor: Colors.blue,
  borderSide: BorderSide(
    width: 2,
    color: Colors.red
  ),
  onPressed: () { },
  child: Text('OutlineButton with custom shape and border'),
)

OutlinedButton(
  style: ButtonStyle(
    shape: MaterialStateProperty.all<OutlinedBorder>(StadiumBorder()),
    side: MaterialStateProperty.resolveWith<BorderSide>(
      (Set<MaterialState> states) {
        final Color color = states.contains(MaterialState.pressed)
          ? Colors.blue
          : Colors.red;
        return BorderSide(color: color, width: 2);
      }
    ),
  ),
  onPressed: () { },
  child: Text('OutlinedButton with custom shape and border'),
)

タイムライン

リリースされたバージョン: 1.20.0-0.0.pre
安定版リリース: 2.0.0

参考文献

API ドキュメント:

  • ButtonStyle
  • ButtonStyleButton
  • ElevatedButton
  • ElevatedButtonTheme
  • ElevatedButtonThemeData
  • OutlinedButton
  • OutlinedButtonTheme
  • OutlinedButtonThemeData
  • TextButton
  • TextButtonTheme
  • TextButtonThemeData

関連する PR:

  • PR 59702: 新しいボタン ユニバース
  • PR 73352: 廃止予定の廃止されたマテリアル クラス: FlatButton、RaizedButton、OutlineButton