why don't the color of the icons change when I change the theme from the app android kotlin compose?

91 Views Asked by At

I added a feature where I can change the theme of the app from the application. It seems to work fine for now, but there is a problem. Even though I specify two icons as light and dark, the color of the icons does not change even if I change the theme. What could be the problem?

Hear is my code:

MainActivity.kt

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    private val themeViewModel: ThemeViewModel by viewModels()

    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)

            DiyetkolikTheme(darkTheme = theme.value) {
               ...

ThemeScreen.kt

@Composable
fun ThemeScreenRoute(
    navHostController: NavHostController,
    viewModel: ThemeViewModel = hiltViewModel()
) {

    val state by viewModel.state.collectAsState()

    ThemeScreen(
        navHostController,
        saveDarkTheme = viewModel::saveDarkTheme,
        saveThemeChoose = viewModel::saveThemeChoose,
        onChangeThemeType = viewModel::onChangeThemeType,
        state
    )
}

@Composable
fun ThemeScreen(
    navHostController: NavHostController,
    saveDarkTheme: (Boolean) -> Unit,
    saveThemeChoose:(ThemeType)->Unit,
    onChangeThemeType:(ThemeType)->Unit,
    state:ThemeScreenState
) {
    
    Scaffold(
        topBar = {
            ScreenTopBar(
                title = stringResource(id = R.string.title),
                img = painterResource(id = R.drawable.ic_back),
                onBackClick = {  }
            )
        }
    ) { it


        val isSystemDarkTheme = isSystemInDarkTheme()

        Column(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            SelectableTitleWithIcon(
                title = "Dark mode",
                shouldShowImage = state.selectedThemeType == ThemeType.DarkTheme,
                onClick = {
                    onChangeThemeType(ThemeType.DarkTheme)
                    saveThemeChoose(ThemeType.DarkTheme)
                    saveDarkTheme(true)
                })
            CustomDivider(startPadding = 15.dp, endPadding = 15.dp)
            SelectableTitleWithIcon(
                title = "Light Mode",
                shouldShowImage = state.selectedThemeType == ThemeType.LightTheme,
                onClick = {
                    onChangeThemeType(ThemeType.LightTheme)
                    saveThemeChoose(ThemeType.LightTheme)
                    saveDarkTheme(false)
                })
            CustomDivider(startPadding = 15.dp, endPadding = 15.dp)
            SelectableTitleWithIcon(
                title = "System Mode",
                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)
        }
    }
}

ThemeViewModel.kt

@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()

    init {
        getThemeChoose()
    }

    private fun getThemeChoose() {

         viewModelScope.launch {
            val themeName = dataStoreHelper.getFirstPreference(PreferenceDataStoreConstants.THEME_CHOOSE, ThemeType.SystemTheme.name)
             _state.update {
                 it.copy(
                     selectedThemeType = ThemeType.fromName(themeName)
                 )
             }
         }
    }

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

AppTheme

@Composable
fun DiyetkolikTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {

    val colors = if (darkTheme) DarkColors else LightColors

    MaterialTheme(
        colors = colors,
        typography = MontSerratTypography(colors),
        content = content,
    )
}

However, I noticed that if it works according to the theme of the emulator. In other words, the icons do not change according to the theme I choose programmatically from my app, for example, if the emulator's theme is dark, the night/icons are displayed. However, if I make the theme light from the app, the system does not work properly because it will still be in dark mode. How can I solve this problem?

0

There are 0 best solutions below