Reputation: 1124
There is a screen in my application that I use to change the theme. There are three options named the same as light theme, dark theme and system. When you click on these options, the theme of the app changes, but the color of the icons does not change. However, I have two types of drawable files, dark and light, my codes are as follows
ThemeScreen
val isSystemDarkTheme = isSystemInDarkTheme()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
SelectableTitleWithIcon(
title = stringResource(id = R.string.karanlik),
shouldShowImage = state.selectedThemeType == ThemeType.DarkTheme,
onClick = {
onChangeThemeType(ThemeType.DarkTheme)
saveThemeChoose(ThemeType.DarkTheme)
saveDarkTheme(true)
})
CustomDivider(startPadding = 15.dp, endPadding = 15.dp)
SelectableTitleWithIcon(
title = stringResource(id = R.string.aydinlik),
shouldShowImage = state.selectedThemeType == ThemeType.LightTheme,
onClick = {
onChangeThemeType(ThemeType.LightTheme)
saveThemeChoose(ThemeType.LightTheme)
saveDarkTheme(false)
})
CustomDivider(startPadding = 15.dp, endPadding = 15.dp)
SelectableTitleWithIcon(
title = stringResource(id = R.string.sistem_ile_ayni),
shouldShowImage = state.selectedThemeType == ThemeType.SystemTheme,
onClick = {
onChangeThemeType(ThemeType.SystemTheme)
saveThemeChoose(ThemeType.SystemTheme)
if (isSystemDarkTheme) saveDarkTheme(true) else saveDarkTheme(false)
})
CustomDivider(startPadding = 15.dp, endPadding = 15.dp)
}
}
ThemeScreenViewModel
@HiltViewModel
class ThemeViewModel @Inject constructor(
private val dataStoreUtil: DataStoreUtil,
private val dataStoreHelper: PreferenceDataStoreHelper
) : ViewModel() {
private val _state = MutableStateFlow(ThemeScreenState())
val state: StateFlow<ThemeScreenState> = _state.asStateFlow()
fun onChangeThemeType(themeType: ThemeType){
_state.update {
it.copy(
selectedThemeType = themeType
)
}
}
fun saveThemeChoose(themeType: ThemeType) {
viewModelScope.launch {
dataStoreHelper.putPreference(PreferenceDataStoreConstants.THEME_CHOOSE, themeType.name)
}
}
fun saveDarkTheme(isDarkTheme: Boolean) {
viewModelScope.launch {
dataStoreUtil.saveTheme(isDarkTheme)
}
}
}
sealed class ThemeType(val name: String) {
object DarkTheme : ThemeType("dark_theme")
object LightTheme : ThemeType("light_theme")
object SystemTheme : ThemeType("system_theme")
object Default : ThemeType("default")
companion object {
fun fromName(name: String): ThemeType {
return when (name) {
DarkTheme.name -> DarkTheme
LightTheme.name -> LightTheme
SystemTheme.name -> SystemTheme
Default.name -> Default
else -> SystemTheme
}
}
}
}
data class ThemeScreenState(
val selectedThemeType: ThemeType = ThemeType.Default
)
MainActivity
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private lateinit var dataStoreUtil: DataStoreUtil
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dataStoreUtil = DataStoreUtil(applicationContext)
val systemTheme = when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> { true }
Configuration.UI_MODE_NIGHT_NO -> { false }
else -> { false }
}
setContent {
val theme = dataStoreUtil.getTheme(systemTheme).collectAsState(initial = systemTheme)
println("theme->"+theme.value)
AppTheme(darkTheme = theme.value) {
...
AppTheme
private val DarkColors = darkColors(
background = md_theme_dark_background,
surface = md_theme_dark_surface,
primary = md_theme_dark_primary,
primaryVariant = md_theme_dark_primary_variant,
onPrimary = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_primary,
onSecondary = md_theme_dark_onPrimaryContainer,
secondaryVariant = md_theme_dark_secondaryContainer,
)
private val LightColors = lightColors(
background = md_theme_light_background,
surface = md_theme_light_surface,
primary = md_theme_light_primary,
primaryVariant = md_theme_light_primary_variant,
onPrimary = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_primary,
onSecondary = md_theme_light_onPrimaryContainer,
secondaryVariant = md_theme_light_primary_variant,
)
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colors = if (darkTheme) DarkColors else LightColors
MaterialTheme(
colors = colors,
typography = MontSerratTypography(colors),
content = content,
)
}
hear is the screenshot
dark mode
light mode
theme.value writes correct in logcat when I change the theme in ThemeScreen for example I choose DarkTheme it print true or when I choose light theme it print false. I also added night icons and light icons as you can see below image Even though I did everything I couldn't do it. Please help me to solve this issue.
Upvotes: 1
Views: 1417
Reputation: 7278
Right now, you are only changing the colors
of your MaterialTheme
when theme changes, which cannot affect the source of drawables that will be used (drawable
or drawable-night
). To change that, you have to set the night mode using AppCompatDelegate.setDefaultNightMode
. You can do that in your MainActivity
like this:
setContent {
val theme = dataStoreUtil.getTheme(systemTheme).collectAsState(initial = systemTheme)
LaunchedEffect(theme) {
snapshotFlow { theme.value }.collect { dark ->
val mode = when {
dark -> AppCompatDelegate.MODE_NIGHT_YES
else -> AppCompatDelegate.MODE_NIGHT_NO
}
AppCompatDelegate.setDefaultNightMode(mode)
}
}
AppTheme(darkTheme = theme.value) {}
}
Upvotes: 0