How would you dynamically switch between theme's color palette with a press of a button inside the app
This is what I am doing so far, but only works when I switch the Android Theme to dark or light mode
AppTheme.Kt
@Model
object ThemeState {
var isLight: Boolean = true
}
@Composable
fun MyAppTheme(
children: @Composable() () -> Unit
) {
MaterialTheme(colors = if (ThemeState.isLight) themeColorsLight else themColorDark) {
children()
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme(children = {
Surface {
Greetings(name = "Android")
}
})
}
}
}
@Composable
fun Greetings(name: String) {
Column(modifier = Modifier.fillMaxHeight()) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = "Hello $name", modifier = Modifier.padding(24.dp),
style = MaterialTheme.typography.h1
)
}
Button(onClick = { ThemeState.isLight = !ThemeState.isLight }) {
Text(text = "Change Theme IsLight:${ThemeState.isLight}")
}
}
}
At the moment I don't have any Idea why your code not works, I'll update this answer when I find out.
but instead of using if
else
for colors
parameter use it for the whole MaterialTheme like this and it will work:
@Composable
fun MyAppTheme(
children: @Composable() () -> Unit
) {
if (ThemeState.isLight) {
MaterialTheme(colors = themeColorsLight) {
children()
}
} else {
MaterialTheme(colors = themColorDark) {
children()
}
}
}
Update: seems that it's bug in Jetpack Compose dev11, I tried in dev12 and it works there.
NOTE 1:
@Model
has been deprecated in dev 12
change your ThemeState
to
object ThemeState {
var isLight by mutableStateOf(true)
}
more information: https://android-review.googlesource.com/c/platform/frameworks/support/+/1311293
NOTE 2
There are some problems with auto Import in recent versions of AndroidStudio
If the Idea throws error: Type 'MutableState<TypeVariable(T)>' has no method 'getValue(ThemeState, KProperty<*>)' and thus it cannot serve as a delegate
Import getValue
and SetValue
manually.
import androidx.compose.getValue
import androidx.compose.setValue
Since 0.1.0-dev16 use these imports:
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
Use AppCompatDelegate class
Step 1: Define a state that will point to Light mode initially.
object ThemeState {
var darkModeState : MutableState<Boolean> = mutableStateOf(false)
}
Note : Whenever this state will be changed, all the methods reading this state value will also be called.
Step 2 : Define a variable for reading state
val isDark = ThemeState.darkModeState.value
Step 3 : Now change Theme mode from Dark to Light and vice versa as follows
Button(onClick = {
val theme = when(isDark){
true -> AppCompatDelegate.MODE_NIGHT_NO
false -> AppCompatDelegate.MODE_NIGHT_YES
}
AppCompatDelegate.setDefaultNightMode(theme)
ThemeState.darkModeState.value = !isDark
}) {
Text(text = "Theme Toggle Button")
}
As you can see here, I'm changing app theme every time Theme Toggle Button is clicked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With