ダークモードは、Android 10(API レベル 29)以降で利用できます。これには次のような利点があります。
- 電力使用量を大幅に削減できます(削減できる量はデバイスの画面テクノロジーに左右されます)。
- 視力の低いユーザーや明るい光に敏感なユーザーにとって、画面の見やすさが向上します。
- 暗い場所でのデバイスの使いやすさが向上します。
ダークモードは、Android システムの UI とデバイスで実行されているアプリに適用されます。
Android 10 以降でダークモードを有効にするには、次の 3 つの方法があります。
- [設定] > [ディスプレイ] > [テーマ] に移動して、システム設定でダークモードを有効にします。
- 有効にすると、クイック設定タイルを使用して通知トレイからテーマを切り替えることができます。
- Google Pixel デバイスでは、バッテリー セーバー モードを有効にすると、ダークモードも同時に有効になります。他のデバイスではこの動作がサポートされていない場合があります。
WebView コンポーネントを使用してウェブベースのコンテンツにダークモードを適用する手順については、WebView でウェブ コンテンツをダークモードにするをご覧ください。
アプリでダークモードをサポートする
ダークモードをサポートするには、アプリのテーマ(通常は res/values/styles.xml にあります)を DayNight テーマから継承するように設定します。
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
マテリアル コンポーネントのダークモードを使用することもできます。
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
これにより、アプリのメインテーマがシステム制御の夜間モードフラグに関連付けられ、有効になっている場合はアプリにデフォルトのダークモードが適用されます。
テーマとスタイル
ライトモードでの使用を想定したハードコードされた色やアイコンは使用しないでください。代わりに、テーマ属性または夜間修飾リソースを使用してください。
ダークモードで最も重要なテーマ属性は次の 2 つです。
?android:attr/textColorPrimary: 汎用のテキストの色。ライトモードではほぼ黒、ダークモードではほぼ白になります。この属性には「無効」状態もあります。?attr/colorControlNormal: 汎用のアイコンの色。この属性には「無効」状態もあります。
マテリアル デザイン コンポーネントを使用することをおすすめします。カラーテーマ システム(テーマ属性 ?attr/colorSurface や ?attr/colorOnSurface など)により、適切な色に簡単にアクセスできるためです。これらの属性はテーマでカスタマイズできます。
アプリ内でテーマを変更する
アプリの実行中にユーザーがアプリのテーマを変更できるようにすることができます。推奨されるオプションは次のとおりです。
- ライト
- ダーク
- システムのデフォルト(推奨されるデフォルト オプション)
これらのオプションは、AppCompat.DayNight モードに直接マッピングされます。
ライト:
MODE_NIGHT_NO。ダーク:
MODE_NIGHT_YES。システムのデフォルト:
MODE_NIGHT_FOLLOW_SYSTEM。
テーマを切り替える手順は次のとおりです。
API レベル 31 以降では、
UiModeManager#setApplicationNightModeを使用して、アプリが実行するテーマをシステムに知らせます。これにより、スプラッシュ画面中にシステムがテーマを一致させることができます。API レベル 30 以下では、
AppCompatDelegate.setDefaultNightMode()を使用してテーマを切り替えます。
フォースダーク
Android 10 には、DayNight テーマを明示的に設定しなくても、デベロッパーがダークモードをすばやく実装できる機能である Force Dark が用意されています。
Force Dark は、ライトモードのアプリの各ビューを分析し、画面に描画される前にダークモードを自動的に適用します。Force Dark とネイティブ実装を組み合わせて使用すると、ダークモードの実装に必要な時間を短縮できます。
アプリで Force Dark を有効にするには、アクティビティのテーマで android:forceDarkAllowed="true" を設定する必要があります。この属性は、Theme.Material.Light など、システムと AndroidX が提供するすべてのライトモードに設定されます。Force Dark を使用する場合は、アプリを徹底的にテストし、必要に応じてビューを除外してください。
アプリでダークモード(Theme.Material など)を使用している場合、Force Dark は適用されません。同様に、アプリのテーマが DayNight テーマを継承している場合、テーマの自動切り替えにより、Force Dark は適用されません。
ビューで強制ダークを無効にする
Force Dark は、android:forceDarkAllowed レイアウト属性または setForceDarkAllowed() を使用して、特定のビューで制御できます。
ウェブ コンテンツ
ウェブベースのコンテンツでダークモードを使用する方法については、WebView でウェブ コンテンツをダークモードにするをご覧ください。WebView に適用されたダークモードの例については、GitHub の WebView デモをご覧ください。
ベスト プラクティス
以下のセクションでは、ダークモードを実装するためのベスト プラクティスについて説明します。
通知とウィジェット
デバイスに表示するものの、直接制御しない UI サーフェスについては、使用するビューにホストアプリのテーマが反映されるようにします。たとえば、通知やランチャー ウィジェットなどです。
通知
MessagingStyle などのシステム提供の通知テンプレートを使用します。つまり、システムが適切なビュースタイルを適用します。
ウィジェットとカスタム通知ビュー
ランチャー ウィジェットの場合、またはアプリでカスタム通知コンテンツ ビューを使用している場合は、ライトモードとダークモードの両方でコンテンツをテストします。
注意すべき一般的な問題は次のとおりです。
- 背景色が常に明るいと想定しています。
- テキストの色をハードコードする。
- デフォルトのテキスト色を使用しながら、ハードコードされた背景色を設定している。
- 静的な色のドローアブル アイコンを使用する。
いずれの場合も、ハードコードされた色の代わりに適切なテーマ属性を使用します。
起動画面
アプリにカスタム起動画面がある場合は、選択したテーマが反映されるように変更が必要になることがあります。
プログラムで白に設定された背景色など、ハードコードされた色を削除します。代わりに ?android:attr/colorBackground テーマ属性を使用してください。
構成の変更
システム設定または AppCompat を通じてアプリのテーマが変更されると、uiMode 構成変更がトリガーされます。つまり、アクティビティは自動的に再作成されます。
場合によっては、アプリで構成変更を処理する必要があります。たとえば、動画の再生中に構成の変更を遅延させる場合などです。
アプリは、各 Activity が uiMode 構成変更を処理できることを宣言することで、ダークモードの実装を処理できます。
<activity
android:name=".MyActivity"
android:configChanges="uiMode" />
Activity が構成変更を処理することを宣言している場合、テーマが変更されると onConfigurationChanged() メソッドが呼び出されます。
アプリで現在のテーマを確認するには、次のようなコードを実行します。
Kotlin
val currentNightMode = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK when (currentNightMode) { Configuration.UI_MODE_NIGHT_NO -> {} // Night mode is not active, we're using the light theme. Configuration.UI_MODE_NIGHT_YES -> {} // Night mode is active, we're using dark theme. }
Java
int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK; switch (currentNightMode) { case Configuration.UI_MODE_NIGHT_NO: // Night mode is not active, we're using the light theme break; case Configuration.UI_MODE_NIGHT_YES: // Night mode is active, we're using dark theme break; }