Getting started
Before diving further into this guide, you should be familiar with:
Preparing the theme
After exporting from Figma the new theme, you should have an extra entry available in your theme.xml
file.
If you have any doubts about how to achieve this, please review the Apply a theme to Android guide again.
Switching themes
Next, we need to implement the logic for switching a theme. The following are suggestions and should not restrict the implementation and architecture of your application.
Step 1
Create a Dynamic Theme file in your project
Copy the following code and add it into your application.
fun AppCompatActivity.selectedTheme() = themePreferences.getInt(ThemeResIdKey, Int.MAX_VALUE)
fun AppCompatActivity.setDynamicThemeIfApply() {
val themeResId = themePreferences.getInt(ThemeResIdKey, Int.MAX_VALUE)
if (themeResId != Int.MAX_VALUE) setTheme(themeResId)
observeThemeChanges()
}
fun AppCompatActivity.setThemeTo(@StyleRes themeResId: Int) {
themePreferences.edit(commit = true) { putInt(ThemeResIdKey, themeResId) }
}
fun AppCompatActivity.setThemeToDefault() {
themePreferences.edit(commit = true) { putInt(ThemeResIdKey, Int.MAX_VALUE) }
}
private fun AppCompatActivity.observeThemeChanges() {
lifecycleScope.launch { themePreferences.selectedThemeFlow.collect { recreate() } }
}
val AppCompatActivity.themePreferences: SharedPreferences
get() = getSharedPreferences(ThemePreferencesKey, Context.MODE_PRIVATE)
private val SharedPreferences.selectedThemeFlow
get() = callbackFlow {
val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
if (ThemeResIdKey == key) trySend(getInt(key, /* defValue = */ Int.MAX_VALUE))
}
registerOnSharedPreferenceChangeListener(listener)
awaitClose { unregisterOnSharedPreferenceChangeListener(listener) }
}
private const val ThemePreferencesKey = "theme_preferences"
private const val ThemeResIdKey = "theme_id"
Step 2
Update your theme at runtime
At any point you can call the function setThemeTo(resId)
and pass the theme resource id as parameter, or in case you want to
use the default theme defined in your AndroidManifest.xml
file, you can call the function setThemeToDefault()
.
if (selectedTheme() == Int.MAX_VALUE) setThemeTo(themeResId =
R.style.AppTheme_Premium) else setThemeToDefault()