Android主Activity调用setTheme后setDefaultNightMode失效问题
问题原因
你遇到的问题本质是Android系统加载主题的时机早于你的Activity代码执行时机:
- 系统启动Activity时,会优先读取
AndroidManifest.xml中为该Activity配置的SplashTheme,此时你的Activity代码还未执行,setDefaultNightMode没有生效,系统会根据当前系统的夜间模式配置初始化Activity的Context资源。 - 你的
SplashTheme继承自父主题Theme.MaterialComponents.DayNight.NoActionBar,属于日夜自适应主题,系统初始化时如果检测到系统夜间模式开启,会直接用夜间模式的配置初始化Context,后续你再调用setDefaultNightMode也不会自动刷新已经创建完成的Context配置,此时调用setTheme(R.style.AppTheme)加载的仍然是基于旧配置的主题资源,就会出现暗色主题的问题。
解决方案
可以任选以下一种方式修复:
方案1:修改启动屏主题为固定亮色(最推荐)
直接让SplashTheme不继承自适应的DayNight主题,改为固定亮色主题,从根源避免系统初始化时加载暗色配置:
<style name="SplashTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> <item name="android:windowBackground">@drawable/splash_screen</item> <!-- 其他和AppTheme一致的基础属性,比如状态栏颜色等,可以在这里单独配置 --> </style>
方案2:手动刷新Activity配置后再加载主题
如果需要SplashTheme必须继承AppTheme,可以在设置夜间模式后手动刷新Context的配置,再调用setTheme:
override fun onCreate(savedInstanceState: Bundle?) { // 优先设置禁用夜间模式 AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO) // 手动更新当前Context的夜间模式配置 val config = resources.configuration val newUiMode = (config.uiMode and Configuration.UI_MODE_NIGHT_MASK.inv()) or Configuration.UI_MODE_NIGHT_NO config.uiMode = newUiMode applyOverrideConfiguration(config) // 再切换回主主题 setTheme(R.style.AppTheme) super.onCreate(savedInstanceState) setContentView(R.layout.activity_main_drawer) }
方案3:将禁用夜间模式逻辑前移到Application层
全局在Application初始化时就设置好夜间模式,确保所有组件创建时都使用统一的配置:
- 自定义Application类:
class MyApplication : Application() { override fun onCreate() { super.onCreate() // 全局禁用夜间模式,应用启动时最先执行 AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO) } }
- 在
AndroidManifest.xml的application标签中注册自定义Application:
<application android:name=".MyApplication" ...其他配置...>
内容的提问来源于stack exchange,提问作者Ignacio C
相关产品推荐
相关产品推荐

