133
96

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FlutterでのMaterial Designのカスタマイズ ~ThemeDataはどこに影響するのか~

Last updated at Posted at 2019-02-25

Flutterは、Material Designを標準サポートしています。そして、テーマを自分で設定できます。
そのために利用するのが、ThemeDataです。
これについて色々な記事があります。

が、日本語はもちろん、英語でも、ThemeDataのプロパティのどこを変更すれば、Widgetのどこに影響するのかを纏めてある記事が見つかりませんでした。

そこで、この記事では自分が愚直にコードを書いて調べたものを記述します。

基本的にここに書いてあるものだけ変更すればそれなりに統一的なデザインになるものを書いてます。

前提

カスタムテーマは MaterialApp の themeプロパティで設定します。
ThemeData() のプロパティにカスタマイズしたい値を設定していきます。

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // TODO ここにカスタマイズしてく
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

基本

Material Designの基本の色設定です。

primarySwatch

  static const MaterialColor _primary = Colors.indigo;
・・・
    primarySwatch: _primary,

ここに書いた色がアプリの基本の色になります。

  • AppBarやbackdropなどの色
  • BottomNavigationのselected(Brightness.lightの場合)
  • TextFieldの選択した時の枠線やアイコンの色(InputDecorationの色)
  • CircleAvatarの色
  • DialogのButtonの色、

prymary1.png prymary2.png
prymary3.png prymary4.png

これだけだとボタンやアイコンなどの色は変わりません。

accentColor

アクセントカラーです。

  static const MaterialAccentColor _accent = Colors.amberAccent;
・・・
    accentColor: _accent,
  • FloatingButtonの色
  • checkbox/radioのselected(Brightness.lightの場合)
  • indicatorの矢印の色
  • DialogのButtonの文字色
  • BottomNavigationのselected(Brightness.darkの場合)

accent.png accent2.png accent3.png

ダイアログ

この状態でのDialogはこんな感じです。
なので、次はダイアログを変えます。

base-dialog.png

colorScheme

ダイアログのボタンの文字色を変えられます。
ただし、RaisedButtonは変わらないので、textStyleの色を変えたほうが良い。
以下のbuttonTheme.textThemeは、ダイアログ以外のその他のボタンのテーマを変えればなおります。

  Button(
    textTheme: Theme.of(context).buttonTheme.textTheme,

onSurface

  • OutlineButtonの枠線の色。注意すべきは、この色に .withOpacity(0.12) をした色になるので薄い。
  • disableボタンもこの色に合わせてくれる
    colorScheme: ColorScheme.fromSwatch(
      primarySwatch: _primary,
    ).copyWith(
      onSurface: _primary,
    ),
button_disable.png

dialogTheme

  • Dialogのボタン以外のテーマを変えれます。
  dialogTheme: DialogTheme(
    titleTextStyle: TextStyle(
    color: _primary,
  )),

ここまでのダイアログです。

dialog.png

ボタン/アイコン

buttonTheme textTheme

  • Dialog以外のボタンの文字色に影響を与える。
    RaisedButtonの場合、ButtonTextTheme.primaryを与えるとよしなにprimayの色にあった白や黒に変えてくれる

buttonTheme shape

  • ボタンの角に影響を与える。
  buttonTheme: ButtonThemeData(
    textTheme: ButtonTextTheme.primary,
    shape: RoundedRectangleBorder(
      /// Dialog以外のボタンの角に影響を与えることができる
      borderRadius: const BorderRadius.all(Radius.circular(24)),
      ),
    ),

button.png button2.png

OutlineButtonの枠線の色をつけたい場合

ThemeDataだけではできません。直接指定する必要があります。

  OutlineButton.icon(
    borderSide: BorderSide(
    color: Theme.of(context).primaryColor.withOpacity(0.5),
  ),

iconTheme

  • 普通のアイコンのテーマを変えられる。
  • IconButton,Iconのどちらも変わる
  iconTheme: const IconThemeData.fallback().copyWith(
    color: _accent,
  ),
icon1.png

accentIconTheme

  • FloatingActionButtonのアイコン色
  accentIconTheme: const IconThemeData.fallback().copyWith(
    color: Colors.red,
  ),
icon2.png

FloatingActionButtonの色

ThemeDataだけでは変えられません。
直接指定する必要があります。ただし、 Theme.of(context)を使いましょう。

  floatingActionButton: FloatingActionButton(
    backgroundColor: Theme.of(context).primaryColor,

primaryIconTheme

  • AppBarなどで利用しているアイコン
  primaryIconTheme: const IconThemeData.fallback().copyWith(
    color: Colors.greenAccent,
  ),

primaryTextTheme

AppBarのアイコンを変えたら、こちらも変えたいでしょう。

  • appBarのタイトルの色が変わる
  primaryTextTheme: const TextTheme().copyWith(
    title: TextStyle().copyWith(
      color: Colors.teal,
    ),
  ),
appbar.png

フォーム

TextFieldなどの枠線の変更です。
動きがないとわからないかもしれないので、下の動画を見てください。

inputDecorationTheme enabledBorder

  • TextFieldなどで設定する枠線の設定を変えられる
  • 利用しているWidgetで InputBorder を指定してもこちらの値が使われる
  inputDecorationTheme: InputDecorationTheme(
    enabledBorder: UnderlineInputBorder(
      borderSide: BorderSide(color: _primary),
    ),

inputDecorationTheme focusedBorder

  • TextFieldなどでonFocusの時の枠線のstyleを設定
    focusedBorder: OutlineInputBorder(
      borderSide: BorderSide(color: _accent),
    ),

inputDecorationTheme labelStyle

  • InputDecorationのlabelTextの色が変えられる
    labelStyle: const TextStyle(        
      color: Colors.orange,
    ),

labelStyle fillColor

  • filed:trueの場所の色を設定できる。
    fillColor: Colors.orange.shade50,

deco.gif

コード

コードです。これのそれぞれの場所を変更すれば、統一的なテーマになるはずです。
(FloatingActionButtonの色とOutlineButtonの枠の色を変えたい場合はそれぞれのWidgetに直接書く必要があります。)

import 'dart:ui';

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

class MyTheme {
  const MyTheme._internal();

  static const MaterialColor _primary = Colors.indigo;
  static const MaterialAccentColor _accent = Colors.amberAccent;

  static final ThemeData data = ThemeData(
    primarySwatch: _primary,
    accentColor: _accent,
    buttonTheme: ButtonThemeData(
      textTheme: ButtonTextTheme.primary,
      shape: RoundedRectangleBorder(
        borderRadius: const BorderRadius.all(Radius.circular(24)),
      ),
    ),
    primaryTextTheme: const TextTheme().copyWith(
      title: TextStyle().copyWith(
        color: Colors.teal,
      ),
    ),
    inputDecorationTheme: InputDecorationTheme(
      enabledBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.green),
      ),
      focusedBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.greenAccent),
      ),
      fillColor: Colors.orange.shade50,
      labelStyle: const TextStyle(
        color: Colors.orange,
      ),
    ),
    iconTheme: const IconThemeData.fallback().copyWith(
      color: _accent,
    ),
    primaryIconTheme: const IconThemeData.fallback().copyWith(
      color: Colors.greenAccent,
    ),
    accentIconTheme: const IconThemeData.fallback().copyWith(
      color: Colors.red,
    ),
    colorScheme: ColorScheme.fromSwatch(
      primarySwatch: _primary,
    ).copyWith(
      onSurface: _primary,
    ),
    dialogTheme: DialogTheme(
        titleTextStyle: TextStyle(
      color: Colors.deepOrange,
    )),
  );
}

ツール

最後に、この記事を書いてる途中で知ったツールを紹介します。
panacheです。

これはGUIでポチポチ選択していくとThemeDataのソースを吐き出してくれます。

Androidアプリがあるので、これでThemeDataを作るのも良いかもしれません。
https://play.google.com/store/apps/details?id=bz.rxla.panache&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1

133
96
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
133
96

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?