[Flutter] 統一感のある色使いを実現しよう！

# 導入
こんにちは、もんすんです。
Flutterで個人開発していると、諸々Widgetに色をつける際、ついつい、一つ一つのWidgetにcolorをしてしまいがちですよね。

それでは、統一感のある色が実現できず、配色もまだらなアプリが出来上がってしまいます。

そこで、今回は、`ColorScheme`を利用してアプリの配色に統一感を持たせました！

# `ColorScheme`とは

Flutterの**ColorScheme**は、アプリ全体のカラーパレットを一元管理するための仕組みです。`Material Design`のガイドラインに沿った色を提供し、テーマ全体の一貫性を保ちやすくします。

## `ColorScheme`の基本的な構造

`ColorScheme`には、以下のような設定項目があり、それぞれに色を設定することができます。

**Primary Colors（主要カラー）**
- `primary`: アプリやブランドのメインカラーとして利用する
- `onPrimary`: primary上に表示されるテキストやアイコンの色
- `primaryContainer`: primaryの変化版、コンテナや背景に使用
- `onPrimaryContainer`: primaryContainer上のテキスト・アイコンの色

**Secondary Colors（補助カラー）**
- `secondary`: 補助的に使われる色
- `onSecondary`: secondary上のテキスト・アイコンの色

**Error Colors（エラーカラー）**
- `error`: エラー表示に使われる色
- `onError`: エラー背景上のテキスト・アイコンの色

**Surface（サーフェス）**
- `surface`: カードやシートのようなサーフェス用
- `onSurface`: サーフェス上のテキスト・アイコンの色

## `ColorScheme`の実装

### `fromSeed`を用いた例

```dart
import 'package:flutter/material.dart';

ColorScheme defaultLightColorScheme = ColorScheme.fromSeed(
    seedColor: Colors.blue, // ベースとなる色
    brightness: Brightness.light, // ライトテーマ
);
```

`ColorScheme.fromSeed`を利用すると、`seedColor`で指定した色から自動で色の組み合わせを生成してくれます。この際に生成される色の組み合わせは、**Material 3**というものに準拠したものになっており、アクセシビリティを考慮したカレーパレットが適用されます。

:::note info
【参考】
https://api.flutter.dev/flutter/material/ColorScheme/ColorScheme.fromSeed.html
:::

また、`brightness`で、ダークテーマかライトテーマかを設定することができます。
これを設定することで、端末の明るさ設定がライトからダークに切り替わったりした際に適用する

### `ColorScheme`を一から作成する例

```dart
import 'package:flutter/material.dart';

ColorScheme defaultColors = ColorScheme.light(
    primary: Colors.blue,
    onPrimary: Colors.green,
    primaryContainer: Colors.blueAccent,
    onPrimaryContainer: Colors.greenAccent,
    secondary: Colors.yellow,
    onSecondary: Colors.black38,
    surface: Colors.white12,
    onSurface: Colors.pink,
    error: Colors.redAccent,
);
```

こちらは、`ColorScheme`の`light`メソッド、もしくは`dark`メソッド内で、使用する色を設定していくものになります。
`fromSeed`と異なり、自分でそれぞれの色を設定することが可能です。
`fromSeed`の欠点としては、自動的にからパレットが決まってしまうことが挙げられますが、こちらでは自分で自由に設定できるというメリットがあります。
一方で、適当に設定してしまうと、アクセシビリティが損なわれます。この上記に示した`ColorScheme`は適当に作成したので、下の方で、如何に酷いかを示します。

## `ColorScheme`の呼び出し

```dart
@override
Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
            // ここに設定します。
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
        ),
        home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
}
```

上記の場合、`seedColor`を`deepPurple`にしたアプリケーションとなります。

<img width='200' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655179/005c8ba9-61a7-1c6e-57a7-0240cdf08a17.png' />

`seedColor`を`blue`に変更すると以下のような色合いになります。
<img width='200' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655179/8e1c7e51-11c7-0035-0e8c-120ea77ef89b.png' />

いい感じの配色に簡単に変更できます。
これならデザイン素人のエンジニアでも配色を気にせず、実装できますね。

また、ダークカラー設定や前述したような別ファイルで定義した`ColorScheme`を利用する場合は、以下のように`MaterialApp`内の実装を変更します。

```dart
return MaterialApp(
    title: 'Flutter Demo',
    theme: ThemeData(
        colorScheme: defaultColors,
        useMaterial3: true,
    ),
    // darkThemeを追加します。
    darkTheme: ThemeData(
        // ここにダークテーマを設定します。
        colorScheme: ColorScheme.dark(
            primary: Colors.blue,
            ... ,
        ),
        useMaterial3: true,
    ),
    home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
```

以下では、`ColorScheme`に上記で実装した[defaultColors]を適用させたものを示します。

<img width='200' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655179/c839ca92-5c3b-6856-81bf-171ccd9ee05b.png' />

正しく適用されました。
しかし、適当ではやはり色合いは良くなさそうですね。
`fromSeed`を利用しない場合は、デザイナーのアドバイスがあったほうが良さそうです。

## `ColorScheme`で指定した色の利用

基本的に`Theme.of(context).colorScheme`を指定し、さらにそこから利用するカラーにあたる設定項目を指定します。

```dart
Text(
    '表示テキスト',
    style: TextStyle(
    color: Theme.of(context).colorScheme.onPrimary,
    ),
),
```

これで、この`Text`の文字色は`ColorScheme`で設定した`onPrimary`の色が適用されます。

# 終わりに

`ColorScheme`を使うことで、Flutterアプリの配色に統一感を持たせることができました。`fromSeed`で簡単に色を生成する方法と、手動で色を設定する方法の両方を紹介しましたが、目的に応じて使い分けるのがポイントです。デザインの知識がなくても`ColorScheme`を活用すれば、見た目の良いアプリを作ることができるので、ぜひ活用してみてください！