如何链接MotionLayout动画

时间:2019-09-04 13:47:24

标签: android-constraintlayout android-transitions android-motionlayout

我的任务是使按钮从“关闭”屏幕移动到屏幕的中心,然后到顶部的动画(请参阅随附的xml和屏幕截图)。因此,基本上,我必须“链接” 2个动画。我的问题是: 我该如何仅使用1个过渡?

我使用doOnEnd()ktx函数使用Transition.TransitionListener实现了它。它可以正常工作,但是代码可能很复杂,因为我还计划在onDestroy()中删除侦听器,以防止内存泄漏。

默认为布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?attr/actionBarSize">

    <View
        android:id="@+id/view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/cardview_dark_background"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text"
        app:layout_constraintTop_toBottomOf="@+id/view"
        app:layout_constraintStart_toEndOf="parent"
        />

</androidx.constraintlayout.motion.widget.MotionLayout>

这是第一个动画的结果:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?attr/actionBarSize">

    <View
        android:id="@+id/view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/cardview_dark_background"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text"
        app:layout_constraintTop_toBottomOf="@+id/view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        />

</androidx.constraintlayout.motion.widget.MotionLayout>

这是第二个动画的结果:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?attr/actionBarSize">

    <View
        android:id="@+id/view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/cardview_dark_background"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text"
        app:layout_constraintTop_toBottomOf="@+id/view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        />

</androidx.constraintlayout.motion.widget.MotionLayout>

活动:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Handler().postDelayed({
            val transitionPhase1 = transitionPhase1()
            transitionPhase1.doOnEnd {
                TransitionManager.beginDelayedTransition(root, transitionPhase2())
            }
            TransitionManager.beginDelayedTransition(root, transitionPhase1)
        }, 2000)
    }

    private fun transitionPhase1(): Transition {
        val constraintSet = ConstraintSet()
        constraintSet.clone(this, R.layout.activity_main_phase_1)
        constraintSet.applyTo(root)
        return AutoTransition()
    }

    private fun transitionPhase2(): Transition {
        val constraintSet = ConstraintSet()
        constraintSet.clone(this, R.layout.activity_main_phase_2)
        constraintSet.applyTo(root)
        return AutoTransition()
    }
}

我希望只有1个TransitionManger.beginDelayedTransition()方法调用。 phase 0 phase 1 phase 2

2 个答案:

答案 0 :(得分:0)

我建议您不要“链接两个过渡”,而是将一个过渡与关键帧一起使用来解决这两个动作。这正是<KeyFrame>的用途。

为此,我建议创建一个scene.xml文件来处理约束集和过渡。

然后,您仅将开始和结束作为constraintSet,并将中间状态设置为关键帧。

让我知道您是否需要有关设置方法的示例。

答案 1 :(得分:-1)

您可以按照下面的步骤将其链接起来:

GitHub

<Transition
    android:id="@+id/startToEnd_materialCardView_email"
    app:constraintSetEnd="@+id/end_materialCardView_email"
    app:constraintSetStart="@+id/start_materialCardView_email"
    app:duration="500">
    <OnClick
        app:clickAction="toggle"
        app:targetId="@+id/start_materialCardView_email" />
</Transition>
<Transition
    android:id="@+id/endToStart_materialCardView_email"
    app:constraintSetEnd="@+id/start_materialCardView_email"
    app:constraintSetStart="@+id/end_materialCardView_email"
    app:duration="500">
    <OnClick
        app:clickAction="toggle"
        app:targetId="@+id/end_materialCardView_email" />
</Transition>

<Transition
    android:id="@+id/startToEnd_materialCardView_password"
    app:constraintSetEnd="@+id/end_materialCardView_password"
    app:constraintSetStart="@+id/end_materialCardView_email"
    app:duration="500">
    <OnClick
        app:clickAction="toggle"
        app:targetId="@+id/start_materialCardView_password" />
</Transition>
<Transition
    android:id="@+id/endToStart_materialCardView_password"
    app:constraintSetEnd="@+id/end_materialCardView_email"
    app:constraintSetStart="@+id/end_materialCardView_password"
    app:duration="500">
    <OnClick
        app:clickAction="toggle"
        app:targetId="@+id/end_materialCardView_password" />
</Transition>

<Transition
    android:id="@+id/startToEnd_materialCardView_birthDate"
    app:constraintSetEnd="@+id/end_materialCardView_birthDate"
    app:constraintSetStart="@+id/end_materialCardView_password"
    app:duration="500">
    <OnClick
        app:clickAction="toggle"
        app:targetId="@+id/start_materialCardView_birthDate" />
</Transition>
<Transition
    android:id="@+id/endToStart_materialCardView_birthDate"
    app:constraintSetEnd="@+id/end_materialCardView_password"
    app:constraintSetStart="@+id/end_materialCardView_birthDate"
    app:duration="500">
    <OnClick
        app:clickAction="toggle"
        app:targetId="@+id/end_materialCardView_birthDate" />
</Transition>

<Transition
    android:id="@+id/startToEnd_materialCardView_phoneNumber"
    app:constraintSetEnd="@+id/end_materialCardView_phoneNumber"
    app:constraintSetStart="@+id/end_materialCardView_birthDate"
    app:duration="1000">
    <OnClick
        app:clickAction="toggle"
        app:targetId="@+id/materialCardView_phoneNumber" />
</Transition>

Inspire Coding