Ionic v7和Angular 17中如何运行时动态切换明暗主题
应用跟随系统主题切换的原理与手动实现方案
一、自动跟随系统主题的底层逻辑
- 系统层面:Android(10+)和iOS(13+)都提供了系统级主题变更的广播机制,比如Android的
ACTION_CONFIGURATION_CHANGED事件、iOS的UIApplication.didChangeStatusBarAppearanceNotification通知,会主动告知应用系统主题模式的变化。 - 资源适配:应用通过分目录/分模式定义资源实现适配。Android中
res/values/对应浅色主题,res/values-night/对应深色主题;iOS则通过Asset Catalog的Color Set或UIColor(dynamicProvider:)方法,为不同主题模式配置对应的颜色、图片等资源。 - 组件自动响应:原生UI组件(如TextView、UIButton)会监听系统主题变更事件,自动加载对应主题下的资源,完成界面样式的更新。
二、运行时手动切换主题的实现方法
Android 端
- 定义多主题样式
在res/values/styles.xml和res/values-night/styles.xml中分别配置浅色、深色主题:
<!-- 浅色主题 --> <style name="AppTheme.Light" parent="Theme.MaterialComponents.Light.NoActionBar"> <item name="colorPrimary">@color/light_primary</item> <item name="colorAccent">@color/light_accent</item> </style> <!-- 深色主题 --> <style name="AppTheme.Dark" parent="Theme.MaterialComponents.Dark.NoActionBar"> <item name="colorPrimary">@color/dark_primary</item> <item name="colorAccent">@color/dark_accent</item> </style>
- 存储用户主题偏好
用SharedPreferences保存用户选择的主题模式:
fun saveThemeMode(mode: String) { getSharedPreferences("ThemePrefs", Context.MODE_PRIVATE) .edit() .putString("selected_theme", mode) .apply() }
- 切换主题并重启页面
在切换按钮的点击事件中设置主题,通过重启Activity生效:
fun switchToDarkTheme() { saveThemeMode("dark") setTheme(R.style.AppTheme_Dark) recreate() } fun switchToLightTheme() { saveThemeMode("light") setTheme(R.style.AppTheme_Light) recreate() } // 在Activity的onCreate中加载保存的主题 override fun onCreate(savedInstanceState: Bundle?) { val themeMode = getSharedPreferences("ThemePrefs", Context.MODE_PRIVATE) .getString("selected_theme", "system") when(themeMode) { "light" -> setTheme(R.style.AppTheme_Light) "dark" -> setTheme(R.style.AppTheme_Dark) else -> { // 跟随系统主题 val currentNightMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK setTheme(if (currentNightMode == Configuration.UI_MODE_NIGHT_YES) R.style.AppTheme_Dark else R.style.AppTheme_Light) } } super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) }
iOS 端
- 配置动态资源
通过Asset Catalog创建Color Set,分别设置Light、Dark模式下的颜色;或用代码生成动态颜色:
let primaryColor = UIColor { traitCollection in traitCollection.userInterfaceStyle == .dark ? UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1) : UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1) }
- 存储用户主题偏好
用UserDefaults保存选择的主题模式:
func saveThemeMode(_ mode: UIUserInterfaceStyle) { UserDefaults.standard.set(mode.rawValue, forKey: "SelectedTheme") }
- 切换主题并刷新界面
直接设置窗口的overrideUserInterfaceStyle,无需重启App:
func switchToDarkTheme() { saveThemeMode(.dark) UIApplication.shared.windows.forEach { window in window.overrideUserInterfaceStyle = .dark } } func switchToLightTheme() { saveThemeMode(.light) UIApplication.shared.windows.forEach { window in window.overrideUserInterfaceStyle = .light } } func switchToSystemTheme() { saveThemeMode(.unspecified) UIApplication.shared.windows.forEach { window in window.overrideUserInterfaceStyle = .unspecified } } // App启动时加载保存的主题 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { if let themeRawValue = UserDefaults.standard.value(forKey: "SelectedTheme") as? Int, let theme = UIUserInterfaceStyle(rawValue: themeRawValue) { UIApplication.shared.windows.forEach { window in window.overrideUserInterfaceStyle = theme } } return true }
内容的提问来源于stack exchange,提问作者notrayen
相关产品推荐
相关产品推荐

