DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Dynamic Theme Switching with DataStore in Compose

Modern Android apps support multiple themes. Using DataStore with Compose makes theme switching seamless and persistent.

DataStore Setup

import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore

private val Context.dataStore by preferencesDataStore("app_preferences")

val DARK_MODE_KEY = booleanPreferencesKey("dark_mode")
val COLOR_SEED_KEY = stringPreferencesKey("color_seed")
Enter fullscreen mode Exit fullscreen mode

Define Your Color Schemes

data class ThemeConfig(val isDarkMode: Boolean, val colorSeed: Long)

val ColorOptions = listOf(
    Color(0xFF6200EE),  // Purple
    Color(0xFF03DAC6),  // Teal
    Color(0xFFBB86FC),  // Light Purple
)
Enter fullscreen mode Exit fullscreen mode

Create ViewModel with DataStore

class ThemeViewModel(private val context: Context) : ViewModel() {
    val themeConfig = context.dataStore.data
        .map { prefs ->
            ThemeConfig(
                isDarkMode = prefs[DARK_MODE_KEY] ?: false,
                colorSeed = prefs[COLOR_SEED_KEY]?.toLong() ?: 0xFF6200EE
            )
        }
        .stateIn(viewModelScope, SharingStarted.Lazily, ThemeConfig(false, 0xFF6200EE))

    fun toggleDarkMode() {
        viewModelScope.launch {
            context.dataStore.edit { prefs ->
                prefs[DARK_MODE_KEY] = !(prefs[DARK_MODE_KEY] ?: false)
            }
        }
    }

    fun setColorSeed(seed: Long) {
        viewModelScope.launch {
            context.dataStore.edit { prefs ->
                prefs[COLOR_SEED_KEY] = seed.toString()
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Apply Theme in Compose

@Composable
fun AppContent(viewModel: ThemeViewModel = LocalThemeViewModel.current) {
    val config by viewModel.themeConfig.collectAsState()

    MaterialTheme(
        colorScheme = if (config.isDarkMode) darkColorScheme() else lightColorScheme(),
    ) {
        // Your app content
    }
}
Enter fullscreen mode Exit fullscreen mode

DataStore provides type-safe, coroutine-based persistence. It's ideal for theme preferences and ensures smooth transitions across app lifecycle.


8 Android app templates (Habit Tracker, Budget Manager, Task Manager, and more) available on Gumroad

Top comments (0)