I have an app with a Dialog in which I allow the change from Dark to Light theme and viceversa. My app used to be in regular XML with fragments and there it would work without an issue, but when migrating to compose Im not able to have the activity be recreated with the theme change.
This is my settings class:
class UserSettings @Inject constructor(@ApplicationContext context: Context) {
private val preferences by lazy {
context.getSharedPreferences(PARCELLIST_PREFS_KEY, Context.MODE_PRIVATE)
}
override var theme: ThemeMode by ThemeModePreferenceDelegate(PREFERENCE_NIGHT_MODE, ThemeMode.SYSTEM)
override val themeModeStream: MutableStateFlow<ThemeMode> = MutableStateFlow(theme)
inner class ThemeModePreferenceDelegate(
private val name: String,
private val default: ThemeMode,
) : ReadWriteProperty<Any?, ThemeMode> {
override fun getValue(thisRef: Any?, property: KProperty<*>): ThemeMode =
ThemeMode.fromOrdinal(preferences.getInt(name, default.ordinal))
override fun setValue(thisRef: Any?, property: KProperty<*>, value: ThemeMode) {
themeModeStream.value = value
preferences.edit { putInt(name, value.ordinal) }
}
}
companion object {
const val PARCELLIST_PREFS_KEY = "ParcelList"
private const val PREFERENCE_NIGHT_MODE = "preference_night_mode"
}
}
This is my activity's oncreate:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val theme = userSettings.themeModeStream.collectAsState()
Timber.w("THEME - Theme is $theme")
val useDarkColors = when (theme.value) {
ThemeMode.SYSTEM -> isSystemInDarkTheme()
ThemeMode.LIGHT -> false
ThemeMode.DARK -> true
}
val windowSizeClass = calculateWindowSizeClass(this)
MyTheme(useDarkColors) {
MyApp(
windowSizeClass
)
}
}
}
And this is my Theme:
fun MyTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
overrideTypography: Typography? = null,
overrideColors: ColorScheme? = null,
content: @Composable () -> Unit,
) {
val colors = overrideColors ?: if (!useDarkTheme) {
LightColors
} else {
DarkColors
}
val typography = overrideTypography ?: MaterialTheme.typography
MaterialTheme(
colorScheme = colors,
content = content,
typography = typography
)
}
Preference changes do work because if i switch to Light mode, after restarting the app my app is in Light mode, and viceversa. It is just not triggering the activity recreation / recompose.