双屏设备中Presentation对话框昼夜模式失效问题求助
双屏设备中Presentation不响应夜间主题的解决方案
问题背景
开发了一款测试双屏设备昼夜主题的小型应用,核心配置如下:
res/values/themes.xml中定义主题:
<style name="Theme.MyApp" parent="Theme.AppCompat.DayNight.NoActionBar"> </style> <style name="Theme.MyApp.CFS"> <!-- 浅色模式背景 --> <item name="android:colorBackground">@color/vivid_tangerine</item> </style>
res/values-night/themes.xml中配置深色主题:
<style name="Theme.MyApp" parent="Theme.AppCompat.DayNight.NoActionBar"> </style> <style name="Theme.MyApp.CFS"> <!-- 深色模式背景 --> <item name="android:colorBackground">@color/malibu_2</item> </style>
MainActivity继承AppCompatActivity,在onCreate中强制夜间模式并创建副屏Presentation:
protected void onCreate(Bundle savedInstanceState) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); @SuppressLint("WrongConstant") DisplayManager displayManager = (DisplayManager) getApplicationContext().getSystemService(Context.DISPLAY_SERVICE); var presentationDisplays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION); var pres = new Pres(this, presentationDisplays[0], R.style.Theme_MyApp_CFS); pres.show(); }
- Manifest中应用主题为
Theme.MyApp,Pres继承自Presentation,布局使用?android:attr/colorBackground作为背景。
问题:主Activity正常应用夜间主题,但副屏Presentation始终显示浅色主题,不响应昼夜模式切换。询问是否可以指定夜间主题文件,或是否需要创建昼夜两套主题按需传入?应用minSdk=21,targetSdk=33。
核心原因
Presentation基于系统原生Context创建,默认不会自动继承AppCompat的昼夜主题切换逻辑。直接传入固定的R.style.Theme_MyApp_CFS只会加载当前默认配置(浅色)的主题,无法根据夜间模式设置自动匹配values-night下的主题。
解决方案
方案一:让Presentation主题支持昼夜切换(推荐)
调整主题继承关系
修改values/themes.xml和values-night/themes.xml中的Theme.MyApp.CFS,让它继承自支持DayNight的父主题:<!-- values/themes.xml --> <style name="Theme.MyApp.CFS" parent="Theme.MyApp"> <item name="android:colorBackground">@color/vivid_tangerine</item> </style><!-- values-night/themes.xml --> <style name="Theme.MyApp.CFS" parent="Theme.MyApp"> <item name="android:colorBackground">@color/malibu_2</item> </style>这样主题会继承
Theme.MyApp的DayNight特性,具备跟随夜间模式切换的能力。为Presentation创建带夜间模式配置的Context
在创建Presentation时,传入已配置夜间模式的Context,确保主题能正确加载对应模式的资源:protected void onCreate(Bundle savedInstanceState) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); Display[] presentationDisplays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION); if (presentationDisplays.length > 0) { // 获取当前应用的夜间模式 int nightMode = AppCompatDelegate.getDefaultNightMode(); // 构建适配夜间模式的Configuration Configuration config = new Configuration(getResources().getConfiguration()); switch (nightMode) { case AppCompatDelegate.MODE_NIGHT_YES: config.uiMode |= Configuration.UI_MODE_NIGHT_YES; break; case AppCompatDelegate.MODE_NIGHT_NO: config.uiMode |= Configuration.UI_MODE_NIGHT_NO; break; default: // 跟随系统则保留原有配置 break; } // 创建带夜间模式配置的Context Context presentationContext = createConfigurationContext(config); // 用新Context创建Presentation Pres pres = new Pres(presentationContext, presentationDisplays[0], R.style.Theme_MyApp_CFS); pres.show(); } }低版本兼容(API 21+)
- 确保AppCompat库版本足够,
Theme.AppCompat.DayNight.NoActionBar在API 21+已做兼容处理 - 若需要动态切换夜间模式,需销毁并重新创建Presentation(低版本不支持动态更新Configuration)
- 确保AppCompat库版本足够,
方案二:直接指定对应模式的主题(简单但不支持动态切换)
如果不需要动态切换夜间模式,可以根据当前模式直接传入对应主题:
int themeId = AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES ? R.style.Theme_MyApp_CFS : R.style.Theme_MyApp_CFS; // 注:此时系统会根据当前模式自动加载values或values-night下的主题 Pres pres = new Pres(this, presentationDisplays[0], themeId);
这种方式仅在创建Presentation时生效,后续切换夜间模式需要重新创建实例。
内容的提问来源于stack exchange,提问作者LoyalPotato
相关产品推荐
相关产品推荐

