如何使用可组合项在应用程序中动态切换浅色和深色主题
How to switch between light and dark theme dynamically in app using composables
您将如何通过在应用程序内按一下按钮在主题的调色板之间动态切换
这就是我目前所做的,但只有当我将 Android 主题切换到深色或浅色模式时才有效
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}")
}
}
}
目前我不知道为什么你的代码不起作用,我会在发现后更新这个答案。
但不要将 if
else
用于 colors
参数,而是像这样将其用于整个 MaterialTheme,它将起作用:
@Composable
fun MyAppTheme(
children: @Composable() () -> Unit
) {
if (ThemeState.isLight) {
MaterialTheme(colors = themeColorsLight) {
children()
}
} else {
MaterialTheme(colors = themColorDark) {
children()
}
}
}
更新:
似乎是 Jetpack Compose dev11 中的错误,我在 dev12 中尝试过,它在那里工作。
注 1:
@Model
已在 dev 12 中弃用
将您的 ThemeState
更改为
object ThemeState {
var isLight by mutableStateOf(true)
}
更多信息:https://android-review.googlesource.com/c/platform/frameworks/support/+/1311293
注 2
AndroidStudio 最新版本auto Import 存在一些问题
如果 Idea 抛出错误:Type 'MutableState<TypeVariable(T)>' has no method 'getValue(ThemeState, KProperty<*>)' and thus it cannot serve as a delegate
手动导入 getValue
和 SetValue
。
import androidx.compose.getValue
import androidx.compose.setValue
自 0.1.0-dev16 使用这些导入:
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
使用AppCompatDelegateclass
第 1 步:定义一个状态,该状态最初将指向 Light 模式。
object ThemeState {
var darkModeState : MutableState<Boolean> = mutableStateOf(false)
}
注意:每当这个状态改变时,所有读取这个状态值的方法也会被调用。
第 2 步:定义读取状态的变量
val isDark = ThemeState.darkModeState.value
第 3 步:现在将主题模式从深色更改为浅色,反之亦然,如下所示
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")
}
如您所见,每次单击 主题切换按钮 时我都会更改应用主题。
您将如何通过在应用程序内按一下按钮在主题的调色板之间动态切换
这就是我目前所做的,但只有当我将 Android 主题切换到深色或浅色模式时才有效
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}")
}
}
}
目前我不知道为什么你的代码不起作用,我会在发现后更新这个答案。
但不要将 if
else
用于 colors
参数,而是像这样将其用于整个 MaterialTheme,它将起作用:
@Composable
fun MyAppTheme(
children: @Composable() () -> Unit
) {
if (ThemeState.isLight) {
MaterialTheme(colors = themeColorsLight) {
children()
}
} else {
MaterialTheme(colors = themColorDark) {
children()
}
}
}
更新: 似乎是 Jetpack Compose dev11 中的错误,我在 dev12 中尝试过,它在那里工作。
注 1:
@Model
已在 dev 12 中弃用
将您的 ThemeState
更改为
object ThemeState {
var isLight by mutableStateOf(true)
}
更多信息:https://android-review.googlesource.com/c/platform/frameworks/support/+/1311293
注 2
AndroidStudio 最新版本auto Import 存在一些问题
如果 Idea 抛出错误:Type 'MutableState<TypeVariable(T)>' has no method 'getValue(ThemeState, KProperty<*>)' and thus it cannot serve as a delegate
手动导入 getValue
和 SetValue
。
import androidx.compose.getValue
import androidx.compose.setValue
自 0.1.0-dev16 使用这些导入:
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
使用AppCompatDelegateclass
第 1 步:定义一个状态,该状态最初将指向 Light 模式。
object ThemeState {
var darkModeState : MutableState<Boolean> = mutableStateOf(false)
}
注意:每当这个状态改变时,所有读取这个状态值的方法也会被调用。
第 2 步:定义读取状态的变量
val isDark = ThemeState.darkModeState.value
第 3 步:现在将主题模式从深色更改为浅色,反之亦然,如下所示
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")
}
如您所见,每次单击 主题切换按钮 时我都会更改应用主题。