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")
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
)
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()
}
}
}
}
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
}
}
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)