MotionLayout:多个累积转换

MotionLayout: multiple cumulative transitions

我正在使用 MotionLayout 并尝试应用一系列转换(在 MotionScene 文件中定义)。例如,Transition1 更改了 View1 的位置,然后 Transition2 随后更改了 View2 的位置。我看到的问题是 Transition2 导致 View1 恢复到其原始布局。我正在使用对 transitionToState() 的调用触发转换(我还尝试使用 setTransition() 明确提供 start/end 状态以进行转换,然后调用 transitionToEnd())。

我在 https://www.raywenderlich.com/8883-motionlayout-tutorial-for-android-getting-started 中看到评论

if you don’t provide an end constraint for a view, it will disappear. This happens because the library doesn’t know which constraints it should apply at the end of the animation

是否还需要在 ConstraintSet 中为 Transition2 添加有关 View1 布局的信息?

https://github.com/googlesamples/android-ConstraintLayoutExamples/blob/master/README.md 中有一个 "Multi State" 示例,但看起来所有转换都从单个基态开始(而不是 "cumulative")

转换不是状态增量。他们从一个州到另一个州。 ConstraintSets 定义了那些状态。

ConstraintSet(在 MotionScene 的上下文中)定义一个状态,即基本布局 + 您在标签中描述的更改。

@hoford所说,ConstraintSets 不会在每次更改时合并。显然,如果不使用反射,这也是不可能的,尽管它肯定有用。无论如何,这里是如何使用反射(通过一些扩展函数)来做到这一点。

我确实创建了我的 own TransitionListener 基础 class 来提供支持注释和可读的值名称。 可以找到扩展函数 here.

你可以做的是合并两个 ConstraintSets 然后变异 endConstraintSet 可以通过 TransitionListener#onTransitionChange:

获得
class AccumulativeTransitionListener: TransitionListener() {

        var didApplyConstraintSet = false

        override fun onTransitionChange(view: MotionLayout, @IdRes startConstraintSetId: Int, @IdRes endConstraintSetId: Int, progress: Float) {
            if (!didApplyConstraintSet) {
                // Let's retrieve our ConstraintSets first
                val startConstraintSet = view.getConstraintSet(startConstraintSetId)
                val endConstraintSet = view.getConstraintSet(endConstraintSetId)
                // Merge them (using an extension function)
                val mergedConstraintSet = startConstraintSet + endConstraintSet
                // Clear + Set them
                endConstraintSet.setConstraints(mergedConstraintSet)
                didApplyConstraintSet = true
            }
        }

        override fun onTransitionCompleted(view: MotionLayout, @IdRes constraintSetId: Int) {
            didApplyConstraintSet = false
        }

    }

为了不在每次调用 TransitionListener#onTransitionChange 时合并和应用 ConstraintSets,有一个简单的辅助变量。

最后,您必须将侦听器附加到您的 MotionLayout:

val accumulativeListener = AccumulativeTransitionListener()
motionLayout.setTransitionListener(accumulativeListener)

让我知道这是否有效或是否有任何错误!