ダークテーマは、Android 10(API レベル 29)以上で利用可能です。次のような特典があります。
- デバイスの画面テクノロジーに応じて、電力使用量を大幅に削減できます。
- 視力の低いユーザーや明るい光に敏感なユーザーにとって、画面の見やすさが向上します。
- 暗い場所でのデバイスの使いやすさが向上します。
ダークテーマは、Android のシステム UI とデバイスで実行中のアプリに適用されます。
Android 10 以降でダークテーマを有効にするには、次の 3 つの方法があります。
- [設定] > [ディスプレイ] > [テーマ] に移動して、システム設定でダークテーマを有効にします。
- [クイック設定] タイルを使用して、通知トレイ(有効にしている場合)からテーマを切り替えます。
- Pixel デバイスでバッテリー セーバー モードを有効にすると、同時にダークテーマも有効になります。他のデバイスでは、この動作がサポートされていない場合があります。
WebView コンポーネントを使用してウェブベースのコンテンツにダークテーマを適用する手順については、WebView のウェブ コンテンツをダークテーマ化するをご覧ください。
アプリでダークテーマをサポートする
ダークテーマをサポートするには、アプリのテーマ(通常は res/values/styles.xml にあります)が DayNight テーマを継承するように設定します。
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
Material Components のダークテーマを使用することもできます。
<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 では、デベロッパー向けのForce Dark機能を使用して、ダークモードを簡単に実装できます。上記の説明のように、DayNight テーマを明示的に設定する必要はありません。
フォースダーク機能は、ライトテーマが設定されているアプリの各ビューを分析し、ダークテーマを自動的に適用してから画面に描画します。Force Dark とネイティブの実装を組み合わせて使用することで、ダークテーマの実装に必要な時間を短縮できます。
アプリは、アクティビティのテーマで android:forceDarkAllowed="true" を設定することにより、Force Dark をオプトインする必要があります。この属性は、すべてのシステムと AndroidX によって提供されるライトテーマ(Theme.Material.Light など)で設定します。Force Dark を使用する場合は、アプリを徹底的にテストし、必要に応じてビューを除外する必要があります。
アプリがダークテーマ(Theme.Material など)を使用している場合、Force Dark は適用されません。同様に、アプリのテーマが DayNight テーマを継承している場合、テーマは自動的に切り替えられるので、フォースダークは適用されません。
ビューで Force Dark を無効にする
android:forceDarkAllowed レイアウト属性または
setForceDarkAllowed() を使用することにより、特定のビューに対するフォースダークの適用を制御できます。
ウェブ コンテンツ
ウェブベースのコンテンツでダークテーマを使用する方法については、WebView のウェブ コンテンツにダークテーマを適用するをご覧ください。WebView にダークテーマ を適用した例については、GitHub の WebView デモをご覧ください 。
ベスト プラクティス
以下のセクションでは、ダークテーマの実装に関するおすすめの方法を紹介します。
通知とウィジェット
デバイスに表示はするが直接管理はしない UI サーフェスに関しては、使用するすべてのビューにホストアプリのテーマを反映することが重要です。通知とランチャー ウィジェットはその好例です。
通知
システムが提供する通知テンプレート(MessagingStyle など)を使用します。つまり、適切なビュースタイルの適用はシステムが行います。
ウィジェットとカスタム通知ビュー
ランチャー ウィジェットを使用する場合や、アプリでカスタムの通知コンテンツ ビューを使用する場合、ライトテーマとダークテーマの両方でコンテンツをテストします。
陥りやすい落とし穴は次のとおりです。
- 背景色は常に明るいと仮定する。
- テキストの色をハードコードする。
- ハードコードされた背景色を設定し、さらにデフォルトのテキストの色を使用する。
- 静的な色のドローアブル アイコンを使用する。
上記のいずれの場合も、ハードコードされた色ではなく、適切なテーマ属性を使用してください。
起動画面
アプリにカスタムの起動画面がある場合、選択したテーマが反映されるようにするために変更が必要になることがあります。
プログラムで白に設定された背景色など、ハードコードされた色はすべて削除します。代わりに、?android:attr/colorBackground テーマ属性を使用してください。
構成の変更
システムの [設定] または AppCompat を介してアプリのテーマが変更されると、it
triggers a 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; }