在 ThemeScreen 中切换后,主题更改未反映在 Jetpack Compose 应用程序中

问题描述 投票:0回答:1

我正在使用 Jetpack Compose 开发 Android 应用程序,并尝试实现动态主题更改功能。主题是使用自定义 PlanstyTheme 函数设置的,用户可以从 ThemeSelectionScreen 中选择主题。主题选择应该立即更新应用程序的外观,但在 ThemeScreen 中切换主题后,更改似乎没有生效。

这是我的 MainActivity 的片段:

class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    val preferences: AppPreferences by inject()
    setContent {
        val viewmodel: MainScreenModel by inject()
        val isOnBoardingDone by preferences.isOnboardingComplete.collectAsState(initial = false)
        val appTheme by viewmodel.appTheme.collectAsState(initial = AppTheme.SYSTEM)
        val accentColor by viewmodel.accentColor.collectAsState(initial = MaterialTheme.colorScheme.primaryContainer)

        Log.i("theme name Main", appTheme.name)
        Log.i("accent theme name Main", "${accentColor.value}")

        PlanstyTheme(appTheme = appTheme, accentColor = accentColor) {
            if (isOnBoardingDone) {
                Navigator(MainContainer)
            } else {
                Navigator(OnboardingScreen)
            }
        }
    }
}

下面是我的主题可组合方法

    @Composable
fun PlanstyTheme(
    appTheme: AppTheme,
    accentColor: Color,
    content: @Composable () -> Unit
) {
    val dark = appTheme == AppTheme.DARK || (appTheme == AppTheme.SYSTEM && isSystemInDarkTheme())

    val colorScheme = when {
        dark -> darkScheme.copy(primary = accentColor)
        else -> lightScheme.copy(primary = accentColor)
    }

    CompositionLocalProvider(
        localColorScheme provides colorScheme
    ) {
        MaterialTheme(
            colorScheme = colorScheme,
            content = content
        )
    }

    // Handle system UI colors
    val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            window.statusBarColor = Color.Transparent.toArgb()
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !dark
        }
    }

我也会粘贴我的数据存储中的代码

    class AppPreferences(private val context: Context) {

    // to make sure there's only one instance
    companion object {
        private val Context.appPreference: DataStore<Preferences> by preferencesDataStore("preferences")

        //keys
        val ONBOARDING_KEY = booleanPreferencesKey("onboarding")
        val POINTS_KEY = intPreferencesKey("points")

        private val THEME_KEY = stringPreferencesKey("theme")
        private val ACCENT_COLOR_KEY = intPreferencesKey("accent_color")
    }

    // themes and accents
    suspend fun saveTheme(theme: AppTheme) {
        context.appPreference.edit { preferences ->
            preferences[THEME_KEY] = theme.name
        }
        Log.i("datastore theme","$theme")
    }

    fun getTheme() = context.appPreference.data.map { preferences ->

       val theme = preferences[THEME_KEY] ?: AppTheme.SYSTEM.name
        Log.i("get datastore theme","$theme")
        AppTheme.valueOf(theme)

    }

    suspend fun saveAccentColor(color: Color) {
        context.appPreference.edit { preferences ->
            preferences[ACCENT_COLOR_KEY] = color.toArgb()
        }
    }

    fun getAccentColor() = context.appPreference.data.map { preferences ->
        preferences[ACCENT_COLOR_KEY]?.let { Color(it) } ?: Color.Gray
    }
}
enum class AppTheme {
    SYSTEM, LIGHT, DARK
}

还有其他代码,如果您需要查看我可以编辑并提供代码,我会将视图模型中的主题更新到数据存储

注意:我使用 voyager 进行导航和屏幕模型 我还注意到,当我改变主题时,状态栏会改变,但整个用户界面不会改变

light mode screenshot! notice the status bardark mode screenshot! Notice the status bar

根据要求,我将添加下面的 MainScreenModel 代码

class MainScreenModel(private val preferences: AppPreferences) : ScreenModel {

val appTheme = preferences.getTheme()

val accentColor = preferences.getAccentColor()}

当我关闭并重新打开应用程序时,主题会发生变化 如果您有任何建议,我真的很感激,我一整天都在这

android android-jetpack-compose themes compose-recomposition
1个回答
0
投票

这似乎得到了

datastore-preferences
的支持?

因此

OnSharedPreferenceChangeListener
无法使用。在 Compose 中,您需要
MutableState
MutableStateFlow
。另请参阅:可组合项中的状态

问题是,您使用

collectAsState()
分配主题,而应该是
mutableStateOf()
mutableStateListOf()
以便可观察并在值更改时触发重组。

val appTheme by viewmodel.appTheme.collectAsState(initial = AppTheme.SYSTEM)
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.