Tim*_*lin 5 android android-theme android-resources android-jetpack-compose
最初,我的应用程序的主题遵循系统的主题,为了方便起见,我为浅色和深色主题创建了可绘制资源。然后我实现了手动更改主题的功能,无论系统主题如何,但显然可绘制资源与系统主题或其他主题相关联。有没有办法以某种方式在夜间和非夜间可绘制资源之间强制切换?
已找到解决方案,如果有问题请指正。
从AppCompatActivity继承我们的Activity而不是ComponentActivity
使用 AppDelegateCompat.setDefaultNightMode() 告诉应用程序我们将使用哪个主题
调用 delegate.applyDayNight()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Getting user's saved selection
appTheme.value = runBlocking(Dispatchers.IO) {
getSavedAppTheme(context)
}
// Telling the application which mode to use
when (appTheme.value) {
AppTheme.SYSTEM_THEME -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
AppTheme.NIGHT_THEME -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
AppTheme.LIGHT_THEME -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
delegate.applyDayNight()
setContent {
MyAppTheme {
MyAppComposable()
}
}
}
Run Code Online (Sandbox Code Playgroud)
处理用户选择:
suspend fun setAppTheme(context: Context, theme: AppTheme) {
// Saving selection to cache
saveAppTheme(context, theme)
// Applying selection
appTheme.value = theme
// Telling the application which mode to use
when (appTheme.value) {
AppTheme.SYSTEM_THEME -> setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM)
AppTheme.NIGHT_THEME -> setDefaultNightMode(MODE_NIGHT_YES)
AppTheme.LIGHT_THEME -> setDefaultNightMode(MODE_NIGHT_NO)
}
}
Run Code Online (Sandbox Code Playgroud)
更新:
第2点最好在Application.onCreate()中调用,以免在onCreate()内重新加载Activity
Ski*_*ᴉʞS -1
您可以做的是使用数据存储并将该切换的值分配给它。然后在setContent {}
您可以将其检查为:
val theme = userSettings.themeStream.collectAsState()
val useDarkColors = when (theme.value) {
AppTheme.MODE_AUTO -> isSystemInDarkTheme()
AppTheme.MODE_DAY -> false
AppTheme.MODE_NIGHT -> true
}
Run Code Online (Sandbox Code Playgroud)
其中 userSettings 是:
enum class AppTheme {
MODE_DAY,
MODE_NIGHT,
MODE_AUTO;
companion object {
fun fromOrdinal(ordinal: Int) = values()[ordinal]
}
}
interface UserSettings {
val themeStream: StateFlow<AppTheme>
var theme: AppTheme
}
class UserSettingsImpl @Inject constructor(
@ApplicationContext context: Context
) : UserSettings {
override val themeStream: MutableStateFlow<AppTheme>
override var theme: AppTheme by AppThemePreferenceDelegate("app_theme", AppTheme.MODE_AUTO)
private val preferences: SharedPreferences =
context.getSharedPreferences("sample_theme", Context.MODE_PRIVATE)
init {
themeStream = MutableStateFlow(theme)
}
inner class AppThemePreferenceDelegate(
private val name: String,
private val default: AppTheme,
) : ReadWriteProperty<Any?, AppTheme> {
override fun getValue(thisRef: Any?, property: KProperty<*>): AppTheme =
AppTheme.fromOrdinal(preferences.getInt(name, default.ordinal))
override fun setValue(thisRef: Any?, property: KProperty<*>, value: AppTheme) {
themeStream.value = value
preferences.edit {
putInt(name, value.ordinal)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
那么应该使用存储的Data Store
而不是使用系统的。
这是Stefano Sansone的完整示例Compose 主题切换器
您还可以阅读Jetpack Compose Theming