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

Android主题切换如何避免屏幕闪烁?单Activity架构无需重启方案

解决方案

1. 禁用系统默认Activity重建行为

首先在AndroidManifest.xml中给你的单主Activity添加configChanges配置,拦截主题变化导致的系统重建,避免导航栈丢失:

<activity
    android:name=".MainActivity"
    android:configChanges="uiMode|screenLayout|screenSize|smallestScreenSize|orientation"
    android:exported="true">
    <!-- 原有intent-filter等配置保持不变 -->
</activity>

2. 添加过渡动画消除闪烁

直接全局重绘View会因为前后色值差异大出现闪烁,可以通过临时快照过渡层实现平滑切换:

调整ThemeManager实现

将Flow收集逻辑和Activity生命周期绑定,避免内存泄漏,同时过滤重复主题触发:

class ThemeManager(
    private val themeDataStore: ThemeDataStore,
    private val coroutineScope: CoroutineScope
) {
    // 加distinctUntilChanged避免相同主题重复触发切换
    val currentThemeFlow = themeDataStore.themeFlow.distinctUntilChanged()

    fun setCurrentTheme(newTheme: Int) {
        coroutineScope.launch {
            themeDataStore.updateTheme(newTheme)
        }
    }
}

// 在主Activity中初始化
val themeManager = ThemeManager(themeDataStore, lifecycleScope)

主Activity中添加切换过渡逻辑

在主ActivityonCreate方法中添加主题变化监听,通过快照过渡消除闪烁:

lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        themeManager.currentThemeFlow.collect { newTheme ->
            val decorView = window.decorView
            // 1. 拍摄当前界面快照作为过渡层
            val snapshot = Bitmap.createBitmap(decorView.width, decorView.height, Bitmap.Config.ARGB_8888)
            val canvas = Canvas(snapshot)
            decorView.draw(canvas)
            val snapshotView = ImageView(this@MainActivity)
            snapshotView.setImageBitmap(snapshot)
            decorView.addView(snapshotView)

            // 2. 执行主题切换
            AppCompatDelegate.setDefaultNightMode(newTheme)

            // 3. 界面重绘完成后淡出过渡层
            snapshotView.animate()
                .alpha(0f)
                .setDuration(150) // 过渡时长可自行调整
                .withEndAction {
                    decorView.removeView(snapshotView)
                    snapshot.recycle()
                }
                .start()
        }
    }
}

3. 冷启动适配

在主Activity的super.onCreate()调用前,先读取存储的主题值调用AppCompatDelegate.setDefaultNightMode()设置,避免冷启动阶段出现闪屏。

内容的提问来源于stack exchange,提问作者Arpit Shukla

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 00:54:02