Chapter 05

Step4: ダークモードでかっこよくしよう

sugit
sugit
2023.05.07に更新

Step4 の概要

Step4 では、MaterialApp のテーマを使ってダークモードを設計してみます。

本章で学べること

  • MaterialApp のテーマを設計する方法

テーマ設計をしてダークモードを実装してみましょう

最近のアプリはだいたいダークモードに対応していますね。
こちらもダークモードに対応しましょう。
ダークモードの対応は Theme で作ります。

いまはこのようになっています。

return MaterialApp(
      title: 'Pokemon Flutter',
      theme: ThemeData.light(),
      home: const TopPage(),
    );

これに 1 行追加して

return MaterialApp(
      title: 'Pokemon Flutter',
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      home: const TopPage(),
    );

これでダークモード対応は完了です。

ですが、ダークモード対応した時は注意深くデザインが壊れていないことを確認した方が良いです。実際、このケースでも Chip のテキストの色がおかしいですね。

Chip の色を黄色にした場合、その明るさを考慮するとダークモードでもライトモードでも文字は黒色であって欲しいですね。でも、これは Chip が黄色だからであって、水タイプを青にしたり、エスパーを紫にした時にも同じことが言えるのでしょうか・・・。

こういうときは ruminance という値を使って分岐させます。

Chip(
  backgroundColor: Colors.yellow,
  label: Text(
    'electric',
    style: TextStyle(
        color: Colors.yellow.computeLuminance() > 0.5
            ? Colors.black
            : Colors.white),
  ),
),

いい感じですね。
とりあえず数色しか使わないのでざっくり判定していますが、まぁまぁ雑なコードです。ありとあらゆるコードが最適で洗練されている必要はないと思っているので、適度に手は抜いています。いろいろな色に対応するならもっとまじめにやる必要があります。以下のメソッドを使ってきっちりやりましょう。

https://api.flutter.dev/flutter/material/ThemeData/estimateBrightnessForColor.html

では続いて、ダークモードとライトモードをデバイスのシステム設定によらず固定してみましょう。
Notion だとこういう設定がありますね。同じです。

MaterialApp にこれは用意されています。

Widget build(BuildContext context) {
    ThemeMode mode = ThemeMode.system;
    return MaterialApp(
      title: 'Pokemon Flutter',
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: mode,   // <-- ここ
      home: const TopPage(),
    );
  }

ThemeMode.system, dark, light が用意されています。これを指定すれば完了です。ここではいったん mode を system にしておいておきます。あとで、この設定をアプリの設定画面に追加し、ここに反映するようにします。そのときにまた使いますので、おいておいてください。