Flutter のダークモード対応方法3種類、①ダークテーマ固定、②デバイスのモード設定に合わせて自動切り替え、③任意のテーマに手動で切り替え、について解説します。
①②は簡単なので、③の解説がメインな感じになっています。
ダークテーマ固定
MaterialApp の theme プロパティにダークテーマを指定すれば、ダークテーマ固定になります。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.dark(), //← これでダークテーマ固定
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
デバイスのモード設定に合わせて自動切り替え
MaterialApp ウィジェットの、
- theme プロパティにライト用テーマを設定
- darkTheme プロパティにダーク用テーマを設定
- themeMode プロパティを ThemeMode.system に設定
以上でデバイスのモード設定に応じて自動的にテーマが切り替わります。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.light(), // ライト用テーマ
darkTheme: ThemeData.dark(), // ダーク用テーマ
themeMode: ThemeMode.system, // モードをシステム設定にする
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
任意のテーマに手動で切り替え
ここで解説するのは最も柔軟な方法です。任意のテーマを複数定義して、いつでも自由にそれらのテーマを切り替える事ができます。
provider パッケージを追加
provider パッケージを使うので、pubspec.yaml に追加します。
今回 provider の説明は省きますが、簡単に説明すると任意のオブジェクトをウイジェット間で自由に参照できたり、値の更新を監視できたりするもので、専門的には、DI【 Dependency Injection 】 依存性注入、と呼ばれるデザインパターンを実現するものです。
※ provider は Flutter 公式も利用を推奨しているパッケージです。
dependencies:
flutter:
sdk: flutter
# ↓これを追加
provider: ^4.0.2
ソースコードでインポートするファイルはこちら:
import 'package:provider/provider.dart';
テーマ変更用の状態クラスを定義
Provider で利用するテーマ変更用の状態クラスを定義します。
// テーマ変更用の状態クラス
class MyTheme extends ChangeNotifier {
ThemeData current = ThemeData.light();
bool _isDark = false;
// とりあえずトグルでテーマを切り替える関数だけ定義しています
toggle() {
_isDark = !_isDark;
current = _isDark ? ThemeData.dark() : ThemeData.light();
notifyListeners();
}
}
使い方
ChangeNotifierProvider の中にウイジェットを入れて、MaterialApp クラスの theme プロパティで MyTheme のカレントテーマを参照するようにします。
// MyApp ウイジェット
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyTheme(),
child: Consumer<MyTheme>(
builder: (context, theme, _) {
return MaterialApp(
theme: theme.current,
home: MyHomePage(title: 'Example'),
);
},
),
);
}
}
テーマを変更したい場所で、MyThemeクラスの toggle 関数を呼び出せば、テーマが切り替わります。
Provider.of<MyTheme>(context, listen: false).toggle();
サンプルコード
全体のサンプルコードです。
右下のフローティングボタンを押すと、トグルでライトとダークのテーマが切り替わります。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// テーマ変更用の状態クラス
class MyTheme extends ChangeNotifier {
ThemeData current = ThemeData.light();
bool _isDark = false;
toggle() {
_isDark = !_isDark;
current = _isDark ? ThemeData.dark() : ThemeData.light();
notifyListeners();
}
}
void main() => runApp(MyApp());
// MyApp ウイジェット
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyTheme(),
child: Consumer<MyTheme>(
builder: (context, theme, _) {
return MaterialApp(
theme: theme.current,
home: MyHomePage(title: 'Example'),
);
},
),
);
}
}
// MyHomePage ウイジェット
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('テーマ切替テスト'),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Provider.of<MyTheme>(context, listen: false).toggle();
},
child: Icon(Icons.autorenew),
),
);
}
}
コメント