Android配置变更后Activity SharedElement返回转场不生效如何解决?
问题根因
配置变更(如屏幕旋转、深色模式切换)触发Activity栈内所有页面销毁重建时,存在两个核心问题:
- 后台的Activity A重建后,系统默认丢失共享元素的返回映射关系,返回时无法匹配到对应transitionName的View
- 前台的全屏Activity B重建后,转场状态未正确恢复,共享元素回调的绑定逻辑无法被系统重新识别
修复方案
1. 修正Activity A代码
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 显式设置共享元素transitionName,确保重建后不丢失 ViewCompat.setTransitionName(fab, "note") setExitSharedElementCallback(MaterialContainerTransformSharedElementCallback()) // 重建场景下延迟转场,等待View绘制完成 if (savedInstanceState != null) { supportPostponeEnterTransition() fab.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { fab.viewTreeObserver.removeOnPreDrawListener(this) supportStartPostponedEnterTransition() return true } }) } fab.setOnClickListener { val intent = Intent(this,NoteActivity::class.java) val options = ActivityOptionsCompat.makeSceneTransitionAnimation( this, fab, "note" ) startActivity(intent, options.toBundle()) } } // 覆写该方法恢复返回转场的共享元素映射 override fun onActivityReenter(resultCode: Int, data: Intent?) { super.onActivityReenter(resultCode, data) supportPostponeEnterTransition() fab.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { fab.viewTreeObserver.removeOnPreDrawListener(this) supportStartPostponedEnterTransition() return true } }) } }
2. 修正Activity B代码
class NoteActivity : AppCompatActivity(R.layout.activity_note) { override fun onCreate(savedInstanceState: Bundle?) { // super.onCreate之前请求窗口转场特性,避免重建后配置丢失 window.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) super.onCreate(savedInstanceState) val rootView = findViewById<View>(android.R.id.content) ViewCompat.setTransitionName(rootView, "note") setEnterSharedElementCallback(MaterialContainerTransformSharedElementCallback()) // 重建场景下延迟转场,等待布局绘制完成 if (savedInstanceState != null) { supportPostponeEnterTransition() rootView.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { rootView.viewTreeObserver.removeOnPreDrawListener(this) supportStartPostponedEnterTransition() return true } }) } window.sharedElementEnterTransition = createTransform(true) window.sharedElementReturnTransition = createTransform(false) } private fun createTransform(enter: Boolean): MaterialContainerTransform { return MaterialContainerTransform(this, enter) .apply { addTarget(android.R.id.content) duration = resources.getInteger(android.R.integer.config_mediumAnimTime).toLong() val startColor = intent.getIntExtra(COLOR, Color.WHITE) val endColor = MaterialColors.getColor( this@NoteActivity, R.attr.colorSurface, Color.WHITE ) if (intent.getBooleanExtra(MOTION, false)) pathMotion = MaterialArcMotion() if (enter) { startContainerColor = startColor endContainerColor = endColor } else { startContainerColor = endColor endContainerColor = startColor } } } }
3. 验证主题配置
确保两个Activity所用主题已开启转场相关配置:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <item name="android:windowActivityTransitions">true</item> <item name="android:windowSharedElementsUseOverlay">false</item> </style>
windowSharedElementsUseOverlay设为false可避免全屏转场时共享元素出现层级闪烁问题。
内容的提问来源于stack exchange,提问作者Prodigy
相关产品推荐
相关产品推荐

