diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 166eb8582a..80d3c849e1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -86,6 +86,7 @@ dependencies { implementation(projects.sync.work) implementation(libs.androidx.activity.compose) + implementation(libs.androidx.appcompat) implementation(libs.androidx.compose.material3.adaptive) implementation(libs.androidx.compose.material3.adaptive.layout) implementation(libs.androidx.compose.material3.adaptive.navigation) diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt index ecc23d80e0..be45862ab7 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt @@ -16,12 +16,16 @@ package com.google.samples.apps.nowinandroid +import android.app.UiModeManager +import android.content.Context +import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.SystemBarStyle import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatDelegate import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -86,6 +90,7 @@ class MainActivity : ComponentActivity() { darkTheme = resources.configuration.isSystemInDarkTheme, androidTheme = Loading.shouldUseAndroidTheme, disableDynamicTheming = Loading.shouldDisableDynamicTheming, + shouldFollowSystemTheme = Loading.shouldFollowSystemTheme, ), ) @@ -100,6 +105,7 @@ class MainActivity : ComponentActivity() { darkTheme = uiState.shouldUseDarkTheme(systemDark), androidTheme = uiState.shouldUseAndroidTheme, disableDynamicTheming = uiState.shouldDisableDynamicTheming, + shouldFollowSystemTheme = uiState.shouldFollowSystemTheme, ) } .onEach { themeSettings = it } @@ -122,6 +128,10 @@ class MainActivity : ComponentActivity() { darkScrim = darkScrim, ) { darkTheme }, ) + setAppTheme( + uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager, + themeSettings = themeSettings, + ) } } } @@ -167,6 +177,30 @@ class MainActivity : ComponentActivity() { } } +/** + * Sets app theme to reflect user choice. + */ +private fun setAppTheme( + uiModeManager: UiModeManager, + themeSettings: ThemeSettings, +) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val mode = when { + themeSettings.shouldFollowSystemTheme -> UiModeManager.MODE_NIGHT_AUTO + themeSettings.darkTheme -> UiModeManager.MODE_NIGHT_YES + else -> UiModeManager.MODE_NIGHT_NO + } + uiModeManager.setApplicationNightMode(mode) + } else { + val mode = when { + themeSettings.shouldFollowSystemTheme -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM + themeSettings.darkTheme -> AppCompatDelegate.MODE_NIGHT_YES + else -> AppCompatDelegate.MODE_NIGHT_NO + } + AppCompatDelegate.setDefaultNightMode(mode) + } +} + /** * The default light scrim, as defined by androidx and the platform: * https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt;l=35-38;drc=27e7d52e8604a080133e8b842db10c89b4482598 @@ -187,4 +221,5 @@ data class ThemeSettings( val darkTheme: Boolean, val androidTheme: Boolean, val disableDynamicTheming: Boolean, + val shouldFollowSystemTheme: Boolean, ) diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivityViewModel.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivityViewModel.kt index 2d22b7d9cd..35e4981fe4 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivityViewModel.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivityViewModel.kt @@ -61,6 +61,9 @@ sealed interface MainActivityUiState { DarkThemeConfig.LIGHT -> false DarkThemeConfig.DARK -> true } + + override val shouldFollowSystemTheme = + userData.darkThemeConfig == DarkThemeConfig.FOLLOW_SYSTEM } /** @@ -82,4 +85,9 @@ sealed interface MainActivityUiState { * Returns `true` if dark theme should be used. */ fun shouldUseDarkTheme(isSystemDarkTheme: Boolean) = isSystemDarkTheme + + /** + * Returns `true` if app theme should follow system theme. + */ + val shouldFollowSystemTheme: Boolean get() = true }