Как связать анимацию MotionLayout

Моя задача - анимировать движение кнопки из "выключенного" экрана сначала в центр экрана, затем вверх (см. Прикрепленный xml и скриншоты). Итак, я должен связать 2 анимации в цепочку. У меня вопрос: как это сделать, используя только 1 переход?

Я реализовал это с помощью Transition.TransitionListener, используя функцию doOnEnd () ktx. И он работает нормально, но код может быть сложным, так как я также планирую удалить прослушиватель в 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>

Вот результат 1-й анимации:

<?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>

А вот результат 2-й анимации:

<?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()
    }
}

Я ожидаю, что будет только один вызов метода TransitionManger.beginDelayedTransition (). фаза 0  фаза 1 этап 2


person Andras Sanislo    schedule 04.09.2019    source источник
comment
что запускает эту анимацию? прокрутка?   -  person user158    schedule 05.09.2019
comment
В приведенном выше коде он запускается с задержкой в ​​2 секунды. Но мне придется перенести этот переход в другой проект, там переход запускается ответом на HTTP-запросы.   -  person Andras Sanislo    schedule 06.09.2019
comment
вы не можете использовать макет движения для такого рода анимации и, честно говоря, вы вообще не используете макет движения, вы просто используете тег motionlayout. Прочтите здесь   -  person user158    schedule 06.09.2019


Ответы (2)


Я предлагаю вам не связывать два перехода в цепочку, а использовать один переход с ключевыми кадрами для решения двух движений. Это именно то, для чего создан <KeyFrame>.

Для этого я бы рекомендовал создать файл scene.xml для обработки наборов ограничений и перехода.

Тогда у вас будет только начало и конец как constraintSet и промежуточное состояние, которое вы настроите как ключевой кадр.

Дайте мне знать, если вам понадобятся примеры того, как это настроить.

person Tobi    schedule 04.11.2020
comment
не могли бы вы привести пример - person Sarah Maher; 27.01.2021

Вы можете связать, как я это сделал ниже:

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>

Вдохновить кодирование

person inspire_coding    schedule 07.08.2020