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

Android配置变更后Activity SharedElement返回转场不生效如何解决?

问题根因

配置变更(如屏幕旋转、深色模式切换)触发Activity栈内所有页面销毁重建时,存在两个核心问题:

  1. 后台的Activity A重建后,系统默认丢失共享元素的返回映射关系,返回时无法匹配到对应transitionName的View
  2. 前台的全屏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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 08:45:03