You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 端

  1. 定义多主题样式
    在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>
  1. 存储用户主题偏好
    用SharedPreferences保存用户选择的主题模式:
fun saveThemeMode(mode: String) {
    getSharedPreferences("ThemePrefs", Context.MODE_PRIVATE)
        .edit()
        .putString("selected_theme", mode)
        .apply()
}
  1. 切换主题并重启页面
    在切换按钮的点击事件中设置主题,通过重启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 端

  1. 配置动态资源
    通过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)
}
  1. 存储用户主题偏好
    用UserDefaults保存选择的主题模式:
func saveThemeMode(_ mode: UIUserInterfaceStyle) {
    UserDefaults.standard.set(mode.rawValue, forKey: "SelectedTheme")
}
  1. 切换主题并刷新界面
    直接设置窗口的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 13:36:01