iOS13からダークモードが増え、アプリで対応する必要が出てきたので対応方法を考えてみました。
下記でデバイスのテーマ設定を取得できる
platformBrightness = MediaQuery.platformBrightnessOf(context);
##InheritedWidgetを使用して、アプリのテーマを切り替える
2020年4月30日追記
inheritFromWidgetOfExactType
は非推奨のAPIになりました
これからはdependOnInheritedWidgetOfExactType
を使用してください
class ThemeSwitcher extends InheritedWidget {
const ThemeSwitcher({
Key key,
@required this.data,
@required Widget child,
}) : assert(child != null),
super(key: key, child: child);
final _ThemeSwitcherWidgetState data;
static _ThemeSwitcherWidgetState of(BuildContext context) {
final ThemeSwitcher _themeswitcher =
context.dependOnInheritedWidgetOfExactType<ThemeSwitcher>();
return _themeswitcher.data;
}
@override
bool updateShouldNotify(ThemeSwitcher widget) => this != widget;
class ThemeSwitcherWidget extends StatefulWidget {
const ThemeSwitcherWidget({
Key key,
@required this.child,
@required this.initialThemeMode,
}) : assert(child != null),
assert(initialThemeMode != null),
super(key: key);
final Widget child;
final ThemeMode initialThemeMode;
@override
_ThemeSwitcherWidgetState createState() => _ThemeSwitcherWidgetState();
}
class _ThemeSwitcherWidgetState extends State<ThemeSwitcherWidget> {
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
ThemeMode themeMode = ThemeMode.light;
@override
void initState() {
super.initState();
loadAppTheme();
}
Future<void> loadAppTheme() async {
final SharedPreferences prefs = await _prefs;
if (prefs.getBool('isDark') == null) {
// 初回起動は端末のテーマ情報を取得しアプリに適用する
final Brightness platformBrightness =
MediaQuery.platformBrightnessOf(context);
switchTheme(platformBrightness == Brightness.dark);
} else {
setState(() {
themeMode = prefs.getBool('isDark') ? ThemeMode.dark : ThemeMode.light;
});
}
}
Future<void> switchTheme(bool val) async {
final SharedPreferences prefs = await _prefs;
prefs.setBool('isDark', val);
setState(() {
themeMode = val ? ThemeMode.dark : ThemeMode.light;
});
}
@override
Widget build(BuildContext context) {
themeMode = themeMode ?? widget.initialThemeMode;
return ThemeSwitcher(
data: this,
child: widget.child,
);
}
}
使い方
void main( {
runApp(
const ThemeSwitcherWidget(
initialThemeMode: ThemeMode.light,
child: App(),
),
);
}
class App extends StatelessWidget {
const App({key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
thememode: ThemeSwitcher.of(context).themeMode,
home: home(),
);
}
}
下記を呼び出してテーマを変更し、アプリ全体に反映する
ThemeSwitcher.of(context).switchTheme(val);