アプリのNight Modeの切り替え(方法:UiModeManager、API≧31)

投稿日:  更新日:

アプリを対象としたNight Modeの切り替えは、AppCompatDelegateとUiModeManagerで行う方法がります。

ここでは、UiModeManagerを使った方法を説明します。

※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照

※環境:Android Studio Jellyfish | 2023.3.1
    Kotlin 1.9.0
    Compose Compiler 1.5.1
    androidx.compose.foundation:foundation 1.5.0

スポンサーリンク

切り替えの方法

アプリケーションフレームワークのUiModeManager経由で行います。

val _uiModeMgr = getSystemService(UI_MODE_SERVICE) as UiModeManager

// YES/NO
_uiModeMgr.setApplicationNightMode(UiModeManager.MODE_NIGHT_NO)
_uiModeMgr.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES)

// CUSTOM(無視される)
_uiModeMgr.setApplicationNightMode(UiModeManager.MODE_NIGHT_CUSTOM)
_uiModeMgr.customNightModeStart = LocalTime.parse("19:10:00")
_uiModeMgr.customNightModeEnd = LocalTime.parse("05:30:00")

// AUTO(無視される)
_uiModeMgr.setApplicationNightMode(UiModeManager.MODE_NIGHT_AUTO)
val _uiModeMgr = LocalContext.current.getSystemService(UI_MODE_SERVICE) as UiModeManager

// YES/NO
_uiModeMgr.setApplicationNightMode(UiModeManager.MODE_NIGHT_NO)
_uiModeMgr.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES)

// CUSTOM(無視される)
_uiModeMgr.setApplicationNightMode(UiModeManager.MODE_NIGHT_CUSTOM)
_uiModeMgr.customNightModeStart = LocalTime.parse("19:10:00")
_uiModeMgr.customNightModeEnd = LocalTime.parse("05:30:00")

// AUTO(無視される)
_uiModeMgr.setApplicationNightMode(UiModeManager.MODE_NIGHT_AUTO)

UiModeManager#setApplicationNightMode( )はAPI31で追加されたメソッドです。ですので、API≧31で利用可能です。

スポンサーリンク

切り替えのタイプ

指定できる切り替えのタイプは2つです。

切り替えのタイプ(UiModeManager.XXX)結果
手動MODE_NIGHT_YESスイッチDark OnNight
MODE_NIGHT_NODark OffDay
自動MODE_NIGHT_AUTO
※無視される
暦に従う日の入時刻Day⇒Night
日の出時刻Night⇒Day
MODE_NIGHT_CUSTOM
※無視される
指定時刻Start時刻Day⇒Night
End時刻Night⇒Day
※isSystemInDarkTheme()はUiModeManagerに切り替えられた結果を返す
  true:Night Mode、false:Day Mode

MODE_NIGHT_CUSTOMとMODE_NIGHT_AUTOは指定できますが、無視されます。切り替えは行われません。

UiModeManagerService#setApplicationNightMode( )
        @Override
        public void setApplicationNightMode(@UiModeManager.NightMode int mode) {
            switch (mode) {
                case UiModeManager.MODE_NIGHT_NO:
                case UiModeManager.MODE_NIGHT_YES:
                case UiModeManager.MODE_NIGHT_AUTO:
                case UiModeManager.MODE_NIGHT_CUSTOM:
                    break;
                default:
                    throw new IllegalArgumentException("Unknown mode: " + mode);
            }
            final int configNightMode;
            switch (mode) {
                case MODE_NIGHT_YES:
                    configNightMode = Configuration.UI_MODE_NIGHT_YES;
                    break;
                case MODE_NIGHT_NO:
                    configNightMode = Configuration.UI_MODE_NIGHT_NO;
                    break;
                default:
                    configNightMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
            }
            final ActivityTaskManagerInternal.PackageConfigurationUpdater updater =
                    mActivityTaskManager.createPackageConfigurationUpdater();
            updater.setNightMode(configNightMode);
            updater.commit();
        }
スポンサーリンク

タイプ:YES/NO

手動で行われるOn/Offのスイッチ動作をします。

YESの時刻でDay⇒Nightへ、NOの時刻でNight⇒Dayへ遷移します。

タイプ:YesNoのタイムチャート

スポンサーリンク

切り替えの反映

切り替えは直ちに反映されます。

Settingsアプリで行った場合と異なるので注意してください。。

切り替えのタイミング

切り替えは構成の変更を伴って行われます。ですので、Activityは再作成されます。

スポンサーリンク

構成の変更

NightとDay Modeの切り替えが行われると、構成の変更が発生し、Activityが再作成されます。これにより、DarkとLight Themeが切り替わります。

Activityの再作成を行いたくなければ、Manifestファイルへ下記のように追記してください。

Activityの再作成は抑制され、onConfigurationChanged()がコールパックされます。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application ...>
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.DarkMode"
			android:configChanges="uiMode">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
class MainActivity : ComponentActivity() {
    ...
    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)

        val _nightMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
        when(_nightMode) {
            Configuration.UI_MODE_NIGHT_NO -> {/* 処理 */}       // Night Mode
            Configuration.UI_MODE_NIGHT_YES -> {/* 処理 */}      // Day Mode
            Configuration.UI_MODE_NIGHT_UNDEFINED -> {/* 処理 */}
            else -> {}
        }
    }
	...
}

Jetpack Composeにおいて、Activityを再作成しない場合でも、LightとDark Themeが切り替わります。

これは、isSystemInDarkTheme()の出力が変わることで、Composable関数(UI要素)の状態が変化し、再Composeが行われるからです。

スポンサーリンク

関連記事:

「Android Studio Giraffe」の作成するプロジェクトは、Jetpack Composeの利用が推奨されます。 そして、作成されたプロジェクトは、Material Designeに準拠したテーマが指定されます。 ※環境:Android Studio Giraffe | 2022.3.1 Patch 1     Kotlin 1.8.10     Compose Compiler 1.4.3 ...
Android端末は自身の置かれている状況を認識して、ユーザーが使い易いように動作を変える仕組みを持ちます。 uiModeのNight(UI_MODE_NIGHT_YES:夜である)とDay(UI_MODE_NIGHT_NO:昼である) は、その「置かれている状況」の一つです。 NightとDayは古くから定義されているモードです。 API29で追加された機能の「Dark Theme」と結びついて、Night Modeの時はDark Themeにする使い方が定番になってしまいました。 その影響でしょうか... Settingsアプリを見ると、Night Modeの影が薄れて、「Drak Themeにする・しない」が主題に作られています。 しかし、裏にNight Modeが存在していることを忘れてはいけません。 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.5.0 ...
システムを対象としたNight Modeの切り替えは、SettingsアプリとUiModeManagerで行う方法がります。 ここでは、Settingsアプリを使った方法を説明します。 ※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.5.0     Emulator 35.1.4-11672324 ...
システムを対象としたNight Modeの切り替えは、SettingsアプリとUiModeManagerで行う方法がります。 ここでは、UiModeManagerを使った方法を説明します。 ※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.5.0 ...
アプリを対象としたNight Modeの切り替えは、AppCompatDelegateとUiModeManagerで行う方法がります。 ここでは、AppCompatDelegateを使った方法を説明します。 ※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.appcompat:appcompat 1.6.1 ...
Activityを対象としたNight Modeの切り替えは、AppCompatDelegateで行う方法があります。 ここでは、AppCompatDelegateを使った方法を説明します。 ※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.appcompat:appcompat 1.6.1 ...
スポンサーリンク