Activity重建动画失效及ViewModel适配主题切换问题
解决主题切换时Activity重建的动画失效及过渡差异问题
一、修复淡入淡出动画不生效的问题
1. 针对recreate()场景的修复
recreate()触发的Activity重建会被系统的配置变更动画覆盖,直接调用overridePendingTransition无效,需要通过主题配置或动态设置窗口动画:
- 方式1:通过主题配置全局动画
在styles.xml中定义包含窗口动画的主题样式:
<!-- 自定义窗口过渡动画样式 --> <style name="ActivityFadeTransition"> <item name="android:windowEnterAnimation">@anim/fade_in</item> <item name="android:windowExitAnimation">@anim/fade_out</item> </style> <!-- 给目标Activity的主题添加动画配置 --> <style name="YourActivityTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="android:windowAnimationStyle">@style/ActivityFadeTransition</item> </style>
在AndroidManifest.xml中给对应Activity指定该主题,切换主题后调用recreate()即可生效。
- 方式2:动态设置窗口动画
在Activity中重写recreate()方法,先设置窗口动画再执行重建:
override fun recreate() { window.setWindowAnimations(R.style.ActivityFadeTransition) super.recreate() }
2. 针对finish()+startActivity场景的修复
确保调用顺序正确,且添加必要的Intent标记避免栈混乱:
// 退出当前Activity时设置淡出动画 finish() overridePendingTransition(R.anim.fade_out, R.anim.fade_in) // 启动新的Activity实例并设置淡入动画 val intent = Intent(this, javaClass) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) startActivity(intent) overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
同时要确保动画资源文件正确,示例fade_in.xml:
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="300" android:fromAlpha="0.0" android:toAlpha="1.0" android:interpolator="@android:anim/decelerate_interpolator" />
fade_out.xml:
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="300" android:fromAlpha="1.0" android:toAlpha="0.0" android:interpolator="@android:anim/accelerate_interpolator" />
二、解决过渡效果与旋转场景的差异问题
配置configChanges="orientation"的旋转不会触发Activity重建,仅执行onConfigurationChanged,系统使用的是窗口旋转动画;而主题切换是完整的销毁-重建流程,默认用Activity启动/退出动画,所以效果差异大。可以通过以下方式统一:
- 方案1:给旋转场景添加自定义动画
在onConfigurationChanged中动态设置窗口动画,让旋转时的过渡和主题切换一致:
override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) window.setWindowAnimations(R.style.ActivityFadeTransition) }
- 方案2:用场景过渡动画模拟旋转效果
给Activity根布局设置过渡名称,使用共享元素过渡让重建过程更平滑:
// 在Activity的onCreate中给根布局设置过渡名 ViewCompat.setTransitionName(findViewById(R.id.root_layout), "root_transition") // 切换主题时使用场景过渡动画启动Activity val options = ActivityOptions.makeSceneTransitionAnimation(this, findViewById(R.id.root_layout), "root_transition") finish() startActivity(Intent(this, javaClass), options.toBundle())
内容的提问来源于stack exchange,提问作者Chuy Porras
相关产品推荐
相关产品推荐

