※ Flutterバージョンは執筆時最新の2.5.0のtagでコードのリンクを載せています。
Flutterはマテリアルデザインをベースに作られているため、 マテリアルデザインに沿ったデザインのアプリを作るときは既存のコンポーネント(Widget)を利用でき爆速で開発できます。 さらに爆速で開発していくためにはデザインコンポーネントを定義していく必要がありますが、 Flutterにはテーマの概念があり、自分で定義した任意のテーマを設定できます。
定義した独自のテーマはMaterialAppに設定できます。
MaterialApp(
title: 'Example App',
theme: lightTheme,
darkTheme: darkTheme,
home: const HomePage(),
);
theme
を設定しない場合は ThemeData.light()
が選択されます。[Code]
一方 darkTheme
を設定しない場合は、端末の設定によって切り替わることはなく theme
に設定した色のみが利用されます。
Flutter内部ではThemeDataにある色のリストから参照されています。[Code]
この部分のコードを見てみると isDark
というフラグがあり、ThemeDataはダークテーマとライトテーマで使い分けています。
final bool isDark = _brightness == Brightness.dark;
また、アクセントカラー等の色は単色で定義されているのですが、マテリアルデザインの基本Widget(Dialog, AppBar, Button, etc…)はそれぞれThemeが設定できます。
e.g. BottomSheetThemeData()
, AppBarTheme()
, CardTheme()
, etc…
ThemeDataの各WidgetにThemeが設定されていない場合は、Widget内部でWidget専用のデフォルトカラーが定義されているかThemeDataのデフォルトカラーが使われています。
Default Colors
デフォルトカラーとして定義されている(個人的に)重要な色をライトテーマとダークテーマに分けてピックアップして書いておきます。
Base Colors
Primary Swatch
アプリ全体のテーマを決める重要なベースカラー
この色を基準にアクセントカラーが決まっている。
Primary Color
Secondary Color
Secondary ColorはColorSchemeに定義されていて、ThemeData.colorScheme
でデフォルトの ColorScheme
が設定されて[Code]
、
ColorScheme.fromSwitch
で定義されています。 [Code]
Accent Color
Error Color
Background Color
画面の背景色 [code]
Skafforld Background Colorが使われていて、CanvasColorの値が読み込まれます。
BottomAppBar, Card, Dialog Color
BottomAppBar, Card, Dialogの背景色
Disabled Color
OnSurface Color
ButtonのDisable時, TextInputFieldのBorder等のベースになる色
使われる時はOpacity(Alpha)の設定がされている事が多い。
Splash Color
ボタンを押した時に表示されるRippleの色等に使われています。
Divider Color
Widget Colors
AppBar
Button
ここではElevated Button
Default
Button ColorLight/Dark#FF2196F3(primaryColor)Disable
Switch
これを調べている時にSwitchはドキュメントが間違っていたのを発見したのでプルリク
しました。
※ 画像はMaterialDesignのサイトから取得。Switch
Switchは、1の部分をThumbと呼び、2の部分をTrackと呼びます。 また、Switchの状態をこのように定義します。
Thumb
- Enabled, On
- Enabled, Off
- Disable, Off
Track
- Enabled, On
- Enabled, Off
- Disable, Off
TextField
Fillが背景色付きのTextFiled 、Outlinedは枠だけのTextFieldを表しています。
Border Color
- Focused
- Filled
InputDecorator.filled
を trueにすると選択される。[Code]
参照元は ThemeData.hintColor
- Default
Background color
- Filled
Decorator.filledをfalseにするとColors.transparent
になる。[Code]
FAB
Secondary Colorが使われます。
PrimarySwatch
ThemeDataのlight, darkはfactory constructorで生成される
ので、PrimarySwatchは Colors.blue
に固定されてしまいます。
TextField等でデフォルトで使われている色はThemeData経由で primarySwatch
を参照するので Accent Color等を変更しても色が変わらないのはこのためです。
そのため、MaterialApp.theme
に ThemeData.light()
を設定している人は TextFieldの色を変更するには TextField.decoration
から直接変更する必要があります。
ちなみにThemeDataで設定するPrimarySwatchはgetterがないので外部からはアクセスできないようになっています。
SwatchなのでSwatchを元にアプリ内のキーカラーを決める仕組みになっていて、デザインシステムから大きくずれない仕組みにしているのだと思います。
仕組みでデザインシステムからずれないようになっているのはとても素晴らしいと思います!!
まとめ
Flutterのデザインシステムはマテリアルデザインを元に作られおり、内部としてはAtomicデザインになっていてとても好きです。
Flutterでアプリを作った際に自動的に設定される色を変えたくても変わらずに困った時は theme_data.dart
, color_scheme
, 各Widgetを見ると大体解決できるので、困った時はこの辺りのソースを見ると良いです。
よく使われるWidgetのデフォルトの色をピックアップしておいたので、Figma等でデザインコンポーネントを作るデザイナーの方にも役立つと嬉しいです。