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)
让我知道这是否有效或是否有任何错误!
我正在使用 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)
让我知道这是否有效或是否有任何错误!