NewPartizal
NewPartizal

Reputation: 1124

why my icon colors or icons does not change when I switch theme in jetpack compose?

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,
    )
}

enter code here

hear is the screenshot

dark mode

enter image description here

light mode

enter image description here

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

Answers (1)

Jan B&#237;na
Jan B&#237;na

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

Related Questions