Android Splash Screen API深色模式适配异常问题求助
Android闪屏主题跟随应用设置不生效问题(三星Android 13设备)
问题描述
使用Android闪屏API实现应用闪屏,深色模式主题开发完成后整体功能正常,但在部分设备(如搭载Android 13(API 33)的三星设备)上出现异常:当应用内切换为浅色模式,但系统深色模式仍处于开启状态时,闪屏仍显示深色主题,仅跟随系统设置而非应用自身主题配置。该问题在Pixel模拟器上不存在。
现有代码实现
主题切换函数
fun changeTheme(context: Context, state: DarkModeState) { SharedPrefsHelper.putInt(Consts.Prefs.DARK_MODE, state.ordinal) val mode = when { state == DarkModeState.ON && isSdk31AndUp -> UiModeManager.MODE_NIGHT_YES state == DarkModeState.ON -> AppCompatDelegate.MODE_NIGHT_YES state == DarkModeState.OFF && isSdk31AndUp -> UiModeManager.MODE_NIGHT_NO state == DarkModeState.OFF -> AppCompatDelegate.MODE_NIGHT_NO state == DarkModeState.SYSTEM && isSdk31AndUp -> UiModeManager.MODE_NIGHT_AUTO state == DarkModeState.SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else -> return } if (isSdk31AndUp) { context.applicationContext.getSystemService(UiModeManager::class.java).apply { setApplicationNightMode(mode) } return } AppCompatDelegate.setDefaultNightMode(mode) }
BaseTheme
<style name="BaseTheme" parent="Theme.AppCompat.DayNight.NoActionBar"> <!-- No Actionbar theme --> <item name="colorPrimary">@color/primary</item> <item name="colorAccent">@color/primary</item> <item name="android:statusBarColor">@color/layerTwoBg</item> <item name="android:windowBackground">@color/surfaceBg</item> <item name="android:forceDarkAllowed" tools:targetApi="q">false</item> </style>
闪屏主题(浅色模式)
res/values/splash_theme.xml
<style name="Theme.AppSplash" parent="Theme.SplashScreen"> <item name="windowSplashScreenBackground">@color/white</item> <item name="android:windowBackground">@color/white</item> <item name="postSplashScreenTheme">@style/AppTheme</item> <item name="android:statusBarColor">@color/white</item> <item name="android:navigationBarColor">@color/white</item> <item name="android:windowLightStatusBar" tools:targetApi="m">true</item> <item name="android:forceDarkAllowed" tools:targetApi="q">false</item> </style>
闪屏主题(深色模式)
res/values-night/splash_theme.xml
<style name="Theme.AppSplash" parent="Theme.SplashScreen"> <item name="windowSplashScreenBackground">@color/surfaceBg</item> <item name="android:windowBackground">@color/surfaceBg</item> <item name="postSplashScreenTheme">@style/AppTheme</item> <item name="android:statusBarColor">@color/surfaceBg</item> <item name="android:navigationBarColor">@color/surfaceBg</item> <item name="android:windowLightStatusBar" tools:targetApi="m">false</item> <item name="android:forceDarkAllowed" tools:targetApi="q">false</item> </style>
启动Activity
override fun onCreate(savedInstanceState: Bundle?) { installSplashScreen() super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) }
AndroidManifest配置
<application android:name=".MyApplication" android:allowBackup="true" android:enableOnBackInvokedCallback="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:networkSecurityConfig="@xml/network_security_config" android:roundIcon="@drawable/ic_launcher" android:screenOrientation="portrait" android:supportsRtl="false" android:theme="@style/Theme.AppSplash" tools:ignore="HardcodedDebugMode" tools:replace="android:supportsRtl"> <activity android:name=".view.main.MainActivity" android:exported="true" android:screenOrientation="portrait" android:windowSoftInputMode="adjustPan"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
依赖配置
implementation "androidx.core:core-splashscreen:1.0.1"
问题根源
Android 12+的Splash Screen API在部分厂商定制系统(如三星One UI)中,应用启动时的闪屏主题加载时机早于应用内主题配置的生效时机,导致系统优先读取系统夜间模式状态,而非应用自身保存的主题设置。
修复方案
1. 提前在Application初始化时设置主题
在MyApplication的onCreate中优先读取保存的主题状态并设置,确保闪屏加载前应用主题已生效:
class MyApplication : Application() { override fun onCreate() { super.onCreate() // 读取保存的深色模式状态 val darkModeOrdinal = SharedPrefsHelper.getInt(Consts.Prefs.DARK_MODE, DarkModeState.SYSTEM.ordinal) val darkModeState = DarkModeState.values()[darkModeOrdinal] // 提前设置应用主题 changeTheme(this, darkModeState) } private fun changeTheme(context: Context, state: DarkModeState) { val mode = when { state == DarkModeState.ON && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> UiModeManager.MODE_NIGHT_YES state == DarkModeState.ON -> AppCompatDelegate.MODE_NIGHT_YES state == DarkModeState.OFF && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> UiModeManager.MODE_NIGHT_NO state == DarkModeState.OFF -> AppCompatDelegate.MODE_NIGHT_NO state == DarkModeState.SYSTEM && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> UiModeManager.MODE_NIGHT_AUTO state == DarkModeState.SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else -> return } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { context.applicationContext.getSystemService(UiModeManager::class.java).apply { setApplicationNightMode(mode) } return } AppCompatDelegate.setDefaultNightMode(mode) } }
2. 强化forceDarkAllowed属性
移除闪屏主题中tools:targetApi="q"限制,确保android:forceDarkAllowed="false"在所有版本生效,避免厂商系统强制切换深色:
<!-- res/values/splash_theme.xml --> <style name="Theme.AppSplash" parent="Theme.SplashScreen"> <!-- 其他属性保留 --> <item name="android:forceDarkAllowed">false</item> </style>
<!-- res/values-night/splash_theme.xml --> <style name="Theme.AppSplash" parent="Theme.SplashScreen"> <!-- 其他属性保留 --> <item name="android:forceDarkAllowed">false</item> </style>
3. 延迟闪屏隐藏(可选)
若前两种方案无效,可通过延迟闪屏隐藏给主题加载留足时间:
override fun onCreate(savedInstanceState: Bundle?) { val splashScreen = installSplashScreen() super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) // 设置闪屏保留条件,等待主题加载完成 var isThemeReady = false splashScreen.setKeepOnScreenCondition { isThemeReady } // 模拟主题加载完成,实际可根据主题设置状态调整延迟时间 Handler(Looper.getMainLooper()).postDelayed({ isThemeReady = true }, 100) setContentView(binding.root) }
验证步骤
- 切换应用主题为浅色,杀死应用进程后重新启动
- 检查三星设备上闪屏是否显示浅色主题
- 确认应用主界面主题切换正常
内容的提问来源于stack exchange,提问作者Baset Esmaeili
相关产品推荐
相关产品推荐

