既存アプリにダークモードを適用する際に詰まったこと
はじめに
MaterialApp に theme と darkTheme を設定すればOK!...と思いきや、なぜか端末がダークモードでもアプリ内ではずっとライトモードのままという現象。
この記事では、意外と見落としがちなネイティブ(iOS/Android)側の設定という原因と、その解決策を解説します。
問題の状況
MaterialApp.router に theme と darkTheme を提供し、themeMode はデフォルト値(ThemeMode.system)に依存していました。
端末設定をダークモードにしてアプリを起動し、スプラッシュ画面でOSの明るさ情報を確認したところ:
final themeBrightness = Theme.of(context).brightness;
final osBrightness = MediaQuery.platformBrightnessOf(context);
print('Theme Brightness: $themeBrightness');
print('OS Brightness: $osBrightness');
期待する結果は両方とも Brightness.dark でしたが、実際は:
flutter: Theme Brightness: Brightness.light
flutter: OS Brightness: Brightness.light
原因の特定
MediaQuery.platformBrightnessOf(context) は、OSが現在どのテーマを適用しているかという「生の情報」をFlutterに伝えます。この「生の値」までもが Brightness.light となっていることから、問題はFlutterの設定よりも前のレイヤー(ネイティブコード)にあると特定できました。
結論:アプリのネイティブ設定で、テーマの自動切り替えがブロックされ、「ライトモード」に固定されていたことが原因でした。
解決策
iOS の設定解除
ios/Runner/Info.plist を開き、以下のキーを探します:
<key>UIUserInterfaceStyle</key>
<string>Light</string>
このキーが <string>Light</string> となっている場合、アプリはOSの設定を無視し、常にライトモードで動作します。
解決策:この <key>...</string> のブロックを Info.plist から完全に削除するか、値を <string>Automatic</string> に変更します。
(削除することで、OSの設定にテーマの決定を委ねるのが最もクリーンな方法です。)
Android の設定確認
android/app/src/main/res/values/styles.xml を開き、アプリの基本テーマの parent 属性を確認します:
<style name="LaunchTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
</style>
もし Theme.AppCompat.Light のようなライト専用のテーマを参照していたら、DayNight が含まれるテーマ(例: Theme.MaterialComponents.DayNight や Theme.AppCompat.DayNight)に変更してください。
まとめ
この問題は、Flutterのコードが正しくても、ネイティブ設定が原因でOSの情報が遮断されていたという典型的な落とし穴でした。
これらの設定を修正した後、必ず以下の手順を実行してください:
- ターミナルで
flutter cleanを実行 - アプリを完全に停止し、再ビルド(Run)します
これで、Flutterアプリはユーザーの端末設定に正しく追従し、美しいダークモードが表示されるはずです!
Discussion