この記事では、Flutterのthemeについて書いていきます。
themeとは
アプリの色やテキストの大きさ・フォント・ボタンの形状を統一し長々と色などを指定する手間を省くことができるウィジェットです。
ThemeDataクラスを利用しMaterialAppにデータを渡します。
以下によく使用されるMaterialDesain3の大枠のカテゴリーをまとめました。
Primaryの4つの色役割
| プロパティ名 | 役割 |
|---|---|
| primary | アプリの主色(AppBar、メインボタン、強調アイコンなど) |
| onPrimary | primary の上に配置する文字やアイコンの色(読みやすいコントラストが自動選択) |
| primaryContainer | カードやコンテナなど、面で主張したいときの背景色 |
| onPrimaryContainer | primaryContainer の上に配置する文字やアイコンの色 |
Secondaryの4つの色役割
| プロパティ名 | 役割 |
|---|---|
| secondary | 補助的なUI要素(フィルタチップ、選択状態のハイライトなど) |
| onSecondary | secondary の上に配置する文字やアイコンの色 |
| secondaryContainer | Primaryより目立たせたくない面やカード、FABの背景色 |
| onSecondaryContainer | secondaryContainer の上に配置する文字やアイコンの色 |
Errorの4つの色役割
| プロパティ名 | 役割 | 主な使用場所 |
|---|---|---|
| error | エラーや危険な状態を示す強調色 | 入力エラー枠、削除ボタン、エラー用アイコンなど |
| onError | error の上に配置する文字・アイコン色 | error 色のボタン上の文字・アイコン |
| errorContainer | エラーメッセージなどの背景面(少し控えめな赤系) | エラーアラートの背景、警告カードの面 |
| onErrorContainer | errorContainer の上に配置する文字・アイコン色 | errorContainer 内の解説テキスト |
Surfaceの4つの色役割
| プロパティ名 | 役割 | 主な使用場所 |
|---|---|---|
| surface | 画面全体の基本となる背景色 | Scaffold の背景、ダイアログのベース面 |
| onSurface | surface の上に配置する基本テキスト・アイコン色 | メインの文章、見出し、アクティブなアイコン |
| surfaceContainer | 背景と区別して浮かせるカードやエリアの面 | Card の背景、ボトムシート、リスト項目 |
| onSurfaceVariant | 少し目立たせたくない(補足的な)テキスト・アイコン色 | サブタイトル |
サンプル
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
// --- ここでアプリ全体の色(テーマ)を決める ---
theme: ThemeData(
// ベースとなる色を1つ指定するだけで、アプリ全体の色が自動で統一される
colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange),
),
home: const MainScreen(),
);
}
}
class MainScreen extends StatelessWidget {
const MainScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// theme で決めたテーマカラーを呼び出して背景色にする
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
title: const Text('Theme の基本デモ'),
),
body: Center(
child: ElevatedButton(
onPressed: () {},
child: const Text('ボタンも自動でテーマ色になる'),
),
),
);
}
}
サンプル
TextThereを使ったサンプルです。
サンプルは13行目です。
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
// アプリ全体のテキストスタイルを定義
theme: ThemeData(
textTheme: const TextTheme(
headlineLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
bodyMedium: TextStyle(fontSize: 16, color: Colors.black87),
),
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
// テーマから textTheme を取得
final textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: AppBar(title: const Text('TextTheme サンプル')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// headlineLarge(大見出し)を適用
Text('大見出し', style: textTheme.headlineLarge),
const SizedBox(height: 12),
// bodyMedium(標準の本文)を適用
Text('これは標準サイズの本文テキストです。', style: textTheme.bodyMedium),
],
),
),
);
}
}
