如何使用可组合物在应用程序中动态在明暗主题之间切换

时间:2020-06-01 17:14:34

标签: android kotlin android-theme android-jetpack-compose

如何通过按应用内的按钮来动态切换主题的调色板

到目前为止,这是我正在做的事情,但仅当我将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}")
        }
    }
}

2 个答案:

答案 0 :(得分:6)

目前我还不知道为什么您的代码不起作用,我将在找到答案后更新此答案。

但不是将if的{​​{1}}用于else参数,而是像这样将其用于整个MaterialTheme,它将起作用:

colors

更新: 似乎是Jetpack Compose dev11中的错误,我在dev12中尝试过,并且在那里工作。

注意1: @Composable fun MyAppTheme( children: @Composable() () -> Unit ) { if (ThemeState.isLight) { MaterialTheme(colors = themeColorsLight) { children() } } else { MaterialTheme(colors = themColorDark) { children() } } } 已在开发版12中弃用 将您的@Model更改为

ThemeState

更多信息:https://android-review.googlesource.com/c/platform/frameworks/support/+/1311293

注意2 在最新版本的AndroidStudio中,自动导入存在一些问题 如果提示抛出错误:object ThemeState { var isLight by mutableStateOf(true) }

手动导入Type 'MutableState<TypeVariable(T)>' has no method 'getValue(ThemeState, KProperty<*>)' and thus it cannot serve as a delegategetValue

SetValue

从0.1.0-dev16开始,请使用以下导入:

import androidx.compose.getValue
import androidx.compose.setValue

答案 1 :(得分:2)

使用AppCompatDelegate

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

正如您在此处看到的,每次点击主题切换按钮时,我都会更改应用主题。