如何使用焦点元素实现共享元素过渡

How to implement shared element transition with focal element

我想在我的应用程序中实现共享元素转换,当一个 activity 的回收器视图项转换为另一个 activity 时,如下所示:https://storage.googleapis.com/spec-host-backup/mio-design%2Fassets%2F15N3n1xwTt0briEbfIvFUG01pMv2d_xaT%2F02-focus-focalelement-do.mp4. (source: https://material.io/design/motion/choreography.html#using-a-focal-element)

也就是说,该项目正在淡出并更改边界,然后新的 activity 淡入。据我所知,它是简单的 AutoTransition,但它不起作用。简单的褪色效果也不行。

因此,目前我只实现了项目获得新背景 activity 然后更改其边界。

因此,我最终在生成的 activity 布局中添加了回收站视图项目的布局。点击的项目的数据(例如标题等)被传送到下一个activity和intent.putExtra()。在这种情况下,共享元素当然是项目的根视图和结果 activity 的根视图。当 activity 启动时,我通过 SharedElementCallback 将项目的数据设置为 activity 中的匹配视图,例如:

setEnterSharedElementCallback(
                object : SharedElementCallback() {
                    override fun onSharedElementStart(...) {
                       val title = intent.getStringExtra(TITLE)                      
                       activity_item_title.text = title
                       ........
                    }

                    override fun onSharedElementEnd(...) {
                    }
                })

这允许在转换开始时显示完全相同的项目视图。然后它应该开始改变它的边界,同时淡出这个项目的视图。在某个时刻(例如在过渡的中间)当初始视图完全淡出时,activity 的 laouyt 出现,逐渐淡入。为此,我们需要在过渡过程中隐藏项目的视图 (View.visibility = View.GONE) 并使 activity 视图可见。可能这不是最好的方法,但我通过向共享元素输入转换添加一个侦听器并使用 Handler().postDelayed:

来解决这个问题
window.sharedElementEnterTransition.addListener(
            object : android.transition.Transition.TransitionListener {
                override fun onTransitionEnd(transition: Transition) {}

                override fun onTransitionResume(transition: Transition) {}

                override fun onTransitionPause(transition: Transition) {}

                override fun onTransitionCancel(transition: Transition) {}

                override fun onTransitionStart(transition: Transition) {  
                        Handler().postDelayed({
                            activity_item.visibility = View.GONE

                            activity_view_1.visibility = View.VISIBLE
                            activity_view_2.visibility = View.VISIBLE
                            .............
                            .............
                            // Also you could e.g. set the background to your activity here, ets.
                            activity_view_root.background = backgroundDrawable 

                        }, 150)  //suppuse that the whole transition length is 300ms
                    }
                }
            })

过渡动画本身可能如下所示:

<transitionSet>
    <targets>
        <target android:targetId="@id/activity_root_view"/>
    </targets>
    <transition
        class="com.organization.app.utils.FadeOutTransition"
        android:duration="150"/>
    <transition
        class="com.organization.app.utils.FadeInTransition"
        android:startDelay="150"/>
    <changeBounds android:duration="300"/>
</transitionSet>

这里使用了自定义 FadeOutTransition 和 FadeInTransition,因为简单的 android <fade/> 动画不适用于共享元素。这些 类 与此处答案中给出的相似:Why Fade transition doesn't work on Shared Element.

创建 return 转换的步骤类似。