Apply user dark mode preference to splashscreen

pull/1718/head
Andrea Severi 10 months ago
parent 55dbe61c65
commit 5afa9defd7
No known key found for this signature in database
GPG Key ID: BF5DFA9B836FBEC3

@ -89,6 +89,7 @@ dependencies {
implementation(projects.sync.work) implementation(projects.sync.work)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.compose.material3.adaptive) implementation(libs.androidx.compose.material3.adaptive)
implementation(libs.androidx.compose.material3.adaptive.layout) implementation(libs.androidx.compose.material3.adaptive.layout)
implementation(libs.androidx.compose.material3.adaptive.navigation) implementation(libs.androidx.compose.material3.adaptive.navigation)

@ -41,6 +41,7 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="uiMode"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

@ -16,12 +16,16 @@
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid
import android.app.UiModeManager
import android.content.Context
import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
@ -108,23 +112,24 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
val darkTheme = shouldUseDarkTheme(uiState) val themeInfo = themeInfo(uiState)
// Update the edge to edge configuration to match the theme // Update the edge to edge configuration to match the theme
// This is the same parameters as the default enableEdgeToEdge call, but we manually // This is the same parameters as the default enableEdgeToEdge call, but we manually
// resolve whether or not to show dark theme using uiState, since it can be different // resolve whether or not to show dark theme using uiState, since it can be different
// than the configuration's dark theme value based on the user preference. // than the configuration's dark theme value based on the user preference.
DisposableEffect(darkTheme) { DisposableEffect(themeInfo.isThemeDark, themeInfo.shouldFollowSystem) {
enableEdgeToEdge( enableEdgeToEdge(
statusBarStyle = SystemBarStyle.auto( statusBarStyle = SystemBarStyle.auto(
android.graphics.Color.TRANSPARENT, android.graphics.Color.TRANSPARENT,
android.graphics.Color.TRANSPARENT, android.graphics.Color.TRANSPARENT,
) { darkTheme }, ) { themeInfo.isThemeDark },
navigationBarStyle = SystemBarStyle.auto( navigationBarStyle = SystemBarStyle.auto(
lightScrim, lightScrim,
darkScrim, darkScrim,
) { darkTheme }, ) { themeInfo.isThemeDark },
) )
setAppTheme(getSystemService(Context.UI_MODE_SERVICE) as UiModeManager, themeInfo)
onDispose {} onDispose {}
} }
@ -141,9 +146,9 @@ class MainActivity : ComponentActivity() {
LocalTimeZone provides currentTimeZone, LocalTimeZone provides currentTimeZone,
) { ) {
NiaTheme( NiaTheme(
darkTheme = darkTheme, darkTheme = themeInfo.isThemeDark,
androidTheme = shouldUseAndroidTheme(uiState), androidTheme = themeInfo.shouldUseAndroidTheme,
disableDynamicTheming = shouldDisableDynamicTheming(uiState), disableDynamicTheming = themeInfo.shouldDisableDynamicTheming,
) { ) {
NiaApp(appState) NiaApp(appState)
} }
@ -162,44 +167,77 @@ class MainActivity : ComponentActivity() {
} }
} }
/** private data class ThemeInfo(
* Returns `true` if the Android theme should be used, as a function of the [uiState]. /**
*/ * Returns `true` if dark theme should be used.
@Composable */
private fun shouldUseAndroidTheme( val isThemeDark: Boolean,
uiState: MainActivityUiState,
): Boolean = when (uiState) {
Loading -> false
is Success -> when (uiState.userData.themeBrand) {
ThemeBrand.DEFAULT -> false
ThemeBrand.ANDROID -> true
}
}
/** /**
* Returns `true` if the dynamic color is disabled, as a function of the [uiState]. * Returns `true` if theme should follow the system settings.
*/ */
val shouldFollowSystem: Boolean,
/**
* Returns `true` if the dynamic color is disabled.
*/
val shouldDisableDynamicTheming: Boolean,
/**
* Returns `true` if the Android theme should be used.
*/
val shouldUseAndroidTheme: Boolean,
)
@Composable @Composable
private fun shouldDisableDynamicTheming( private fun themeInfo(uiState: MainActivityUiState): ThemeInfo {
uiState: MainActivityUiState, return when (uiState) {
): Boolean = when (uiState) { Loading -> ThemeInfo(
Loading -> false isThemeDark = isSystemInDarkTheme(),
is Success -> !uiState.userData.useDynamicColor shouldFollowSystem = false,
shouldDisableDynamicTheming = false,
shouldUseAndroidTheme = false
)
is Success -> {
val isThemeDark = uiState.userData.darkThemeConfig == DarkThemeConfig.DARK
val shouldFollowSystem = uiState.userData.darkThemeConfig == DarkThemeConfig.FOLLOW_SYSTEM
ThemeInfo(
isThemeDark = isThemeDark || (shouldFollowSystem && isSystemInDarkTheme()),
shouldFollowSystem = shouldFollowSystem,
shouldDisableDynamicTheming = !uiState.userData.useDynamicColor,
shouldUseAndroidTheme = uiState.userData.themeBrand == ThemeBrand.ANDROID
)
}
}
} }
/** /**
* Returns `true` if dark theme should be used, as a function of the [uiState] and the * Sets app theme to reflect user choice.
* current system context.
*/ */
@Composable private fun setAppTheme(
private fun shouldUseDarkTheme( uiModeManager: UiModeManager,
uiState: MainActivityUiState, themeInfo: ThemeInfo
): Boolean = when (uiState) { ) {
Loading -> isSystemInDarkTheme() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
is Success -> when (uiState.userData.darkThemeConfig) { uiModeManager.setApplicationNightMode(
DarkThemeConfig.FOLLOW_SYSTEM -> isSystemInDarkTheme() if (themeInfo.shouldFollowSystem) {
DarkThemeConfig.LIGHT -> false UiModeManager.MODE_NIGHT_AUTO
DarkThemeConfig.DARK -> true } else if (themeInfo.isThemeDark) {
UiModeManager.MODE_NIGHT_YES
} else {
UiModeManager.MODE_NIGHT_NO
}
)
} else {
AppCompatDelegate.setDefaultNightMode(
if (themeInfo.shouldFollowSystem) {
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
} else if (themeInfo.isThemeDark) {
AppCompatDelegate.MODE_NIGHT_YES
} else {
AppCompatDelegate.MODE_NIGHT_NO
}
)
} }
} }

Loading…
Cancel
Save