Flutterで動的にテーマを変更したい!
概要
今回の記事では、Flutterで動的にテーマを変更する手順を掲載する。
仕様書
環境
- Android Studio Giraffe | 2023.2.1 Patch 2
- Flutter 3.19.6
- flutter_riverpod: 2.5.1
手順書
インストール編とコード編の2部構成です。
インストール編
ターミナルでコマンドを実行するか
flutter pub add flutter_riverpod
pubspec.yaml
のdependencies:
に下記のような感じで追加して
dependencies:
flutter_riverpod: ^2.5.1
ターミナルでflutter pub get
する。
flutter pub get
コード編
'DropdownButton`でテーマを選択するとテーマが動的に変更される例。
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
Brightness getTheme(BuildContext context, String str) {
switch (str) {
case "light":
return Brightness.light;
case "dark":
return Brightness.dark;
case "device":
default:
return MediaQuery.platformBrightnessOf(context);
}
}
class MyApp extends ConsumerWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themeStateNotifierProvider);
return MaterialApp(
title: 'Flutter Test',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: getTheme(context, theme)),
useMaterial3: true,
),
home: Scaffold(
body: DynamicThemeSample1( deviceTheme: MediaQuery.platformBrightnessOf(context), )
)
);
}
}
final themeStateNotifierProvider =
StateNotifierProvider<ThemeStateNotifier, String>((ref) {
return ThemeStateNotifier();
});
class ThemeStateNotifier extends StateNotifier<String> {
ThemeStateNotifier() : super("device");
void update(String theme) {
state = theme;
}
}
class DynamicThemeSample1 extends StatefulWidget {
final Brightness deviceTheme;
const DynamicThemeSample1({super.key, required this.deviceTheme});
@override
DynamicThemeState createState() => DynamicThemeState();
}
class DynamicThemeState extends State<DynamicThemeSample1> {
String selectedTheme = 'device';
@override
Widget build(BuildContext context) {
return SafeArea(
child: Center(
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Text(
AppLocalizations.of(context)!.hello,
),
Consumer(
builder: (BuildContext context, WidgetRef ref, Widget? child) {
return DropdownButton<String>(
value: selectedTheme,
onChanged: (String? value) {
setState(() {
selectedTheme = value ?? "device";
});
ref
.read(themeStateNotifierProvider.notifier)
.update(selectedTheme);
},
items: [
DropdownMenuItem(
value: 'device',
child: Text('デバイスの設定を使う(${widget.deviceTheme == Brightness.light ? "Light" : "Dark" })'),
),
const DropdownMenuItem(
value: 'light',
child: Text('Light'),
),
const DropdownMenuItem(
value: 'dark',
child: Text('Dark'),
),
],
);
},
),
]),
),
);
}
}
親のMaterialApp
のプロパティを動的に変更するためにfullter_riverpod
のStateNotifierProvider
を使ってる。()
まとめ(感想文)
APIにアクセスするとかネットワークを使う場合に特に便利だ!