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

Jetpack Compose自定义主题模式下启动屏适配问题

自定义主题适配启动屏的解决方案

问题核心

你已经实现了自定义主题切换,但切换主题后首次启动应用时,启动屏无法正确应用新的主题设置,第二次启动才显示正常。这是因为启动屏主题的设置时机和偏好值读取的异步性冲突导致的。

根本原因

当前代码中,SplashViewModel通过异步协程读取偏好设置的主题值,但installSplashScreen()的执行早于偏好值加载完成,导致首次启动时使用了_isDarkMode的初始默认值(true),等偏好值更新时,启动屏已经无法动态修改主题。

解决方案

直接在Activity的onCreate方法中同步读取偏好主题值,确保在初始化启动屏之前就拿到正确的主题配置,再设置启动屏主题。

修改代码

  1. 在Activity中注入UserRepository,同步读取主题值:
@Inject
lateinit var splashViewModel: SplashViewModel
@Inject
lateinit var repository: UserRepository // 添加该注入

@RequiresApi(Build.VERSION_CODES.S)
override fun onCreate(savedInstanceState: Bundle?) {
    // 同步读取偏好中的主题设置,确保启动屏初始化前拿到正确值
    val isDarkMode = runBlocking {
        repository.readDarkModePreference().first()
    }

    // 初始化启动屏并立即设置对应主题
    val splashScreen = installSplashScreen()
    if (isDarkMode) {
        splashScreen.setSplashScreenTheme(R.style.Theme_App_StartingDarkMode)
    } else {
        splashScreen.setSplashScreenTheme(R.style.Theme_App_StartingLightMode)
    }

    // 保持启动屏显示直到加载完成
    splashScreen.setKeepOnScreenCondition {
        splashViewModel.isLoading.value
    }

    super.onCreate(savedInstanceState)
    // 以下setContent代码保持不变
    setContent {
        val userViewModel: UserViewModel = viewModel()
        val isDarkTheme =  userViewModel.getSavedTheme().collectAsState(initial = true).value
        userViewModel.observeLifecycleEvents(LocalLifecycleOwner.current.lifecycle)
        SharpWalletTheme(darkTheme = isDarkTheme) {
            val startDestination by splashViewModel.startDestination
            val navController = rememberNavController()

            val isUserAuth by userViewModel.isUserAuth
            Surface(
                modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background
            ) {
                RootNavigationGraph(
                    navHostController = navController,
                    startDestination = startDestination,
                    userViewModel = userViewModel,
                    toAuthUser = isUserAuth,
                )
            }
        }
    }
}
  1. 确保启动屏主题的Style配置正确(对应深色/浅色):
<!-- 浅色启动屏主题 -->
<style name="Theme.App.StartingLightMode" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/light_splash_bg</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash_light</item>
    <item name="postSplashScreenTheme">@style/SharpWalletTheme.Light</item>
</style>

<!-- 深色启动屏主题 -->
<style name="Theme.App.StartingDarkMode" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/dark_splash_bg</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash_dark</item>
    <item name="postSplashScreenTheme">@style/SharpWalletTheme.Dark</item>
</style>

关键说明

  • 使用runBlocking同步读取Flow的第一个值是安全的,因为偏好设置必然存在默认值或用户已设置的值,不会长时间阻塞主线程。
  • 启动屏主题必须在installSplashScreen()之后立即设置,避免启动屏绘制后无法修改主题样式。
  • postSplashScreenTheme要与应用的对应主题匹配,保证启动屏到应用界面的过渡流畅无闪烁。

内容的提问来源于stack exchange,提问作者Ravikant sahu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:15:01