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

