ThemeDataのプロパティprimarySwatchについてまとめてみた【初心者脱却シリーズ】

ThemeDataのプロパティprimarySwatchについてまとめてみた【初心者脱却シリーズ】

どうもこんにちはコウヘイです。

本シリーズは、Flutterについて完全初心者の私がFlutterをある程度使えるようになるまで頑張るをテーマに日々の作業ログを記録する内容になります。


以下のような疑問を持ちました。


Material Appのデザインをカスタマイズしたいと思いました。ThemeDataのprimarySwachで全体の色を変更できるみたいですが、どうやるのかわかりません。


今回はFlutterのMaterial Appの色のカスタマイズ方法についてまとめたいと思います。

それでは本題。
今回は以下の内容になります。

著者情報

ちなみにですが、私は5年以上IT系エンジニアとして働いており、主にJavaを主戦場にしています。Webアプリケーションと業務系のアプリケーションの経験を持つごく普通のエンジニアです。

ThemeDataのプロパティprimarySwachについて

MaterialAppのプロパティthemeではアプリのデザインスタイルを指定することができます。

themeにデザインスタイルを指定するためには、ThemeDataクラスを指定する必要があり、

全体の色を決めるためにThemeDataにはプロパティprimarySwachが用意されています。

基本的な使い方

primarySwachにMaterialColorクラスを指定することでアプリの色を変更できます。

MaterialColorは事前にColorsクラス内でいくつか定義されているものがあり、特にカスタマイズする必要がない場合は使うことができます。

指定方法は以下です。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
      title: 'calendar app',
      theme: ThemeData(
        primarySwatch: Colors.indigo, // ここ
      ),
(省略)
}



MaterialColorはColorクラスのように単色を指すわけではなく、10パターンの色の組み合わせを指します。

たとえば、上記の例のColors.indigoは以下のように定義されています。

  static const MaterialColor indigo = MaterialColor(
    _indigoPrimaryValue,
    <int, Color>{
       50: Color(0xFFE8EAF6),
      100: Color(0xFFC5CAE9),
      200: Color(0xFF9FA8DA),
      300: Color(0xFF7986CB),
      400: Color(0xFF5C6BC0),
      500: Color(_indigoPrimaryValue),
      600: Color(0xFF3949AB),
      700: Color(0xFF303F9F),
      800: Color(0xFF283593),
      900: Color(0xFF1A237E),
    },
  );
  static const int _indigoPrimaryValue = 0xFF3F51B5;

MaterialColorを作成し、指定も可

一方、事前に定義されているMaterialColor以外を使用したい場合も当然ながらでてくると思います。

そういった場合は自分で定義したMaterialColorを指定することでカスタマイズすることが可能です。

今回は全体を白に統一したかったので、以下のようなMaterialColorを作成しました。

import 'package:flutter/material.dart';

class Common {
  static const int _primaryValue = 0xFFFFFFFF;
  static const MaterialColor primaryColor = MaterialColor(
    _primaryValue,
    <int, Color>{
      50: Color(0xFFFFFFFF),
      100: Color(0xFFFFFFFF),
      200: Color(0xFFFFFFFF),
      300: Color(0xFFFFFFFF),
      400: Color(0xFFFFFFFF),
      500: Color(_primaryValue),
      600: Color(0xFFFFFFFF),
      700: Color(0xFFFFFFFF),
      800: Color(0xFFFFFFFF),
      900: Color(0xFFFFFFFF),
    },
  );
}



以下のように作成したMaterialColorを指定することで、テーマの色を変更することができます。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
      title: 'calendar app',
      theme: ThemeData(
        primarySwatch: Common.primaryColor, // ここ
      ),
(省略)
}

primarySwachの影響範囲について

アプリの色をカスタマイズできることはわかりました。

次に、MaterialColorの10パターンがどこで使用されるのか疑問に思ったのでまとめたいと思います。

primarySwatchはtheme_data.dart内で定義されていて、10パターンの色はこの中で使われています。

以下、使われている箇所の抜粋です。

primaryColor ??= isDark ? Colors.grey[900] : primarySwatch;
primaryColorBrightness ??= estimateBrightnessForColor(primaryColor);
primaryColorLight ??= isDark ? Colors.grey[500] : primarySwatch[100];
primaryColorDark ??= isDark ? Colors.black : primarySwatch[700];
toggleableActiveColor ??= isDark ? Colors.tealAccent[200] : (accentColor ?? primarySwatch[600]);
accentColor ??= isDark ? Colors.tealAccent[200] : primarySwatch[500];
secondaryHeaderColor ??= isDark ? Colors.grey[700] : primarySwatch[50];
textSelectionColor ??= isDark ? accentColor : primarySwatch[200];
textSelectionHandleColor ??= isDark ? Colors.tealAccent[400] : primarySwatch[300];
backgroundColor ??= isDark ? Colors.grey[700] : primarySwatch[200];
buttonColor ??= isDark ? primarySwatch[600] : Colors.grey[300];
primaryColorBrightness ??= estimateBrightnessForColor(primaryColor);


上記を見る限り、primarySwatch[50]などで指定した色を別のパラメータにいれていることがわかります。

おそらくaccentColorなどのパラメータをアプリ内部で使用しているのでしょう。
※それぞれのパラメータの範囲は調査中です。

なるほど、こうやって内部で使われているから10パターンの色の指定が必要なんだと腑に落ちました。

一方、theme_data.dart内ではprimarySwatch[800]とprimarySwatch[900]が使用されてませんでした。
このことから、外部から指定できるだろうと思い、調べたところやはり指定することが可能だったので次に解説します。

ThemeDataのパラメータを使用する方法

Theme.of(context)を使用することで、ThemeDataにアクセスすることができます。

つまり、Theme.ofはThemeDataを返す関数で、前の章で抜粋したパラメータを使用することができます。

たとえば、以下のようにすればアクセス可能です。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
      title: 'calendar app',
      theme: ThemeData(
        primarySwatch: Common.primaryColor,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Calendar App'),
          leading: IconButton(
              icon: Icon(Icons.menu),
              onPressed: () {
                (省略)
              },
          ),
          backgroundColor: Theme.of(context).accentColor, // ここ
        ),
(省略)
}



また、primarySwatch[800]とprimarySwatch[900]の色を使用したい場合は以下のように直接MaterialColorから取得します。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
      title: 'calendar app',
      theme: ThemeData(
        primarySwatch: Common.primaryColor,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Calendar App'),
          leading: IconButton(
              icon: Icon(Icons.menu),
              onPressed: () {
                (省略)
              },
          ),
          backgroundColor: Common.primaryColor.shade900, // ここ
        ),
(省略)
}



つまり、MaterialColorには10パターンの色を取得するためのゲッターが用意されています。以下、MaterialColorクラスから抜粋したコードになります。

  /// The lightest shade.
  Color get shade50 => this[50];

  /// The second lightest shade.
  Color get shade100 => this[100];

  /// The third lightest shade.
  Color get shade200 => this[200];

  /// The fourth lightest shade.
  Color get shade300 => this[300];

  /// The fifth lightest shade.
  Color get shade400 => this[400];

  /// The default shade.
  Color get shade500 => this[500];

  /// The fourth darkest shade.
  Color get shade600 => this[600];

  /// The third darkest shade.
  Color get shade700 => this[700];

  /// The second darkest shade.
  Color get shade800 => this[800];

  /// The darkest shade.
  Color get shade900 => this[900];

まとめ

以上、FlutterのThemeDataのプロパティprimarySwatchについてでした。

primarySwatchはThemeDataクラス内のその他のプロパティに影響するパラメータであることがわかりました。

これを理解して開発することで曖昧さがなくなり、自信を持ってパラメータを指定することができるようになりました。

デザインについてはユーザビリティを向上する上で大きな要因だとおもうので、これからも重点的に学んでいきたいと思います。
(デザインに疎いです笑)

これからも個人開発がんばります。

どなたかの参考になれば幸いです。


人気記事:【最新】Flutter学習におすすめの入門書3選