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

AppCompatDelegate.setDefaultNightMode在SDK24及以上不触发Activity动画问题

问题分析与解决方案

问题背景

配置了如下窗口动画样式:

<style name="Theme.App" parent="Theme.Material3.DayNight">
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>

<style name="WindowAnimationTransition" parent="@android:style/Animation.Activity">
    <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
    <item name="android:windowExitAnimation">@android:anim/fade_out</item>
    <item name="android:activityOpenEnterAnimation">@android:anim/fade_in</item>
    <item name="android:activityOpenExitAnimation">@android:anim/fade_out</item>
    <item name="android:activityCloseEnterAnimation">@android:anim/fade_in</item>
    <item name="android:activityCloseExitAnimation">@android:anim/fade_out</item>
</style>

调用AppCompatDelegate.setDefaultNightMode()后,Android 21-23版本中Activity重建时动画正常生效,但SDK 24及以上版本动画无法触发,推测是系统优化导致Activity未重建仅部分重渲染。


结论:这是预期行为

从Android 7.0(API 24)开始,AppCompat库对夜间模式切换的处理做了性能优化:不再强制销毁并重建Activity,而是通过更轻量的方式直接更新主题相关的UI元素(比如通过applyOverrideConfiguration或局部UI刷新),避免了Activity重建的开销。

你配置的windowAnimationStyle依赖Activity的创建/销毁流程触发——只有当Activity被重建时,系统才会调用窗口的进入/退出动画。API 24+版本跳过了Activity重建步骤,自然不会触发这些动画,这和你查阅文档后的推测一致。


解决方案

如果需要在夜间模式切换时保留动画效果,有两种可行方案:

1. 手动触发Activity重建并指定动画

在调用setDefaultNightMode()后,主动调用Activity.recreate(),并通过overridePendingTransition()显式指定动画:

// 设置夜间模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
// 指定切换动画
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
// 重建Activity
recreate()

注意:这种方式会重建Activity,需要确保页面的状态(如输入内容、滚动位置等)能通过onSaveInstanceState()和onRestoreInstanceState()正确保存恢复。

2. 添加视图级主题切换动画

无需重建Activity,直接给页面根布局或关键UI元素添加淡入淡出动画,在主题切换前后触发:

val rootView = window.decorView.rootView
// 先播放淡出动画
rootView.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out))

// 切换夜间模式
AppCompatDelegate.setDefaultNightMode(newMode)

// 主题切换完成后播放淡入动画
rootView.postDelayed({
    rootView.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in))
}, 200)

这种方式更轻量,避免了Activity重建的开销,适合对性能要求较高的场景。


内容的提问来源于stack exchange,提问作者Bitwise DEVS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:05:09