14

I'm playing around with the MotionLayout in Android. I'm using the alpha 2 version.

'com.android.support.constraint:constraint-layout:2.0.0-alpha2'

I want to react to two different button clicks and trigger an animation for each of them. My current approach is to set two Transitions in the MotionScene with an OnClick trigger in each one.

The problem is that only the first transition seems to be found. For the second one just nothing happens. Am I doing something wrong or can you just set one transition per MotionScene? If that's the case ist there a different solution to the problem?

Here are the important parts of my Motion Scene

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">

<Transition
    motion:constraintSetStart="@id/startHome"
    motion:constraintSetEnd="@id/endHome"
    motion:duration="300">
    <OnClick
        motion:mode="toggle"
        motion:target="@+id/imageView_bottom_home" />
</Transition>

<Transition
    motion:constraintSetStart="@id/startSearch"
    motion:constraintSetEnd="@id/endSearch"
    motion:duration="300">
    <OnClick
        motion:mode="toggle"
        motion:target="@+id/imageView_bottom_search" />
</Transition>

<ConstraintSet android:id="@+id/startSearch">
    <Constraint
        android:id="@id/imageView_bottom_search"
        ...startConstraints... />
</ConstraintSet>

<ConstraintSet android:id="@+id/endSearch">
    <Constraint
        android:id="@id/imageView_bottom_search"
        ...endConstraints... />
</ConstraintSet>

<ConstraintSet android:id="@+id/startHome">
    <Constraint
        android:id="@id/imageView_bottom_home"
        ...startConstraints... />
</ConstraintSet>

<ConstraintSet android:id="@+id/endHome">
    <Constraint
        android:id="@id/imageView_bottom_home"
        ...endConstraints... />
</ConstraintSet>

Any help appreciated.

Best regards

aba
  • 163
  • 1
  • 7

4 Answers4

12

I had the same problem. The solution I found was to select which one transitions:

(in java code)...

MotionLayout motionConteiner = findViewById(R.id.motion_container);
button1.setOnClickListener((v) -> {
            motionConteiner.setTransition(R.id.start1, R.id.end1);
            motionConteiner.transitionToEnd();//                
        });
button2.setOnClickListener((v) -> {
            motionConteiner.setTransition(R.id.start2, R.id.end2);
            motionConteiner.transitionToEnd();//                
        });
close_file
  • 131
  • 1
  • 4
  • 2
    Thanks for your response! I figured that this is a way to make it work but it blows the idea of having all parts of the animation in the xml. Basically the Transitions in the xml are obsolete then. Maybe it's just not possible by now to have more than one Transition. – aba Oct 28 '18 at 14:34
  • So even if you want to start the animation by default without any button click, this code needs to be used. And it's nowhere mentioned in the Android Docs. – Lalit Fauzdar Mar 20 '20 at 07:16
  • This solution is also the way it's done in official sample apps - https://github.com/android/views-widgets-samples/blob/master/ConstraintLayoutExamples/motionlayout/src/main/java/com/google/androidstudio/motionlayoutexample/histogramdemo/HistogramWidget.kt#L164 – frangulyan Apr 02 '20 at 00:23
0

I think aba is right. I am also having problem adding multiple transitions to a single scene file. Theoretically, MotionLayout should support this because every transition will have a separate trigger (often as click or swipe). Maybe this is a bug with MotionLayout that needs to be fixed. Out of my experience, only the first transition that is encountered in the scene file is cared for. So, currently, I don't think there is a way to support more than one transition in a layout description (scene). To put it more specifically, all motion needs to be started once with the same trigger.

codezombie
  • 2,354
  • 4
  • 35
  • 73
0

A more kotlin'y answer:

with(view as MotionLayout) {
    setTransition(R.id.startState, R.id.endState)
    transitionToEnd()
}
Dambakk
  • 397
  • 3
  • 15
0

Seems to me that MotionLayout only supports one Transition, when you add a second Transition to the MotionScene file the second Transition appears to be ignored. You can however have multiple MotionLayouts in your layout and create a MotionScene for each MotionLayout. This will also keep the MotionScene file cleaner and allow for easier maintenance.

In your layout file, you'll need a Parent layout that can contain multiple MotionLayout files.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        ...
    </data>

    <!-- [databinding] {"msg":"Only one layout element with 1 view child is allowed. So a Parent Layout is required for Multiple motion layouts. -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.constraintlayout.motion.widget.MotionLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutDescription="@xml/motion_scene_01"
            tools:context=".menu.contextual.FragmentContextualOne"
            tools:showPath="true">

            <Button
                android:id="@+id/btn_one"
                android:layout_width="64dp"
                android:layout_height="64dp"
                tools:layout_editor_absoluteX="8dp"
                tools:layout_editor_absoluteY="310dp" />
        </androidx.constraintlayout.motion.widget.MotionLayout>

        <androidx.constraintlayout.motion.widget.MotionLayout
            android:id="@+id/m2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutDescription="@xml/motion_scene_02">

            <Button
                android:id="@+id/btn_two"
                android:layout_width="64dp"
                android:layout_height="64dp"
                tools:layout_editor_absoluteX="8dp"
                tools:layout_editor_absoluteY="500dp" />
        </androidx.constraintlayout.motion.widget.MotionLayout>
    </FrameLayout>
</layout>

Motion Scene One.

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

        <Transition
            android:id="@+id/transition_sine_wave"
            motion:constraintSetStart="@+id/wave_start"  
            motion:constraintSetEnd="@+id/wave_end"
            motion:duration="2000"
            motion:motionInterpolator="linear">
            <OnClick
                motion:touchAnchorId="@+id/btn_one"
                motion:touchAnchorSide="right"
                motion:targetId="@+id/btn_one"/>
        </Transition>

    <ConstraintSet android:id="@+id/wave_start">
        <Constraint
            android:id="@+id/btn_one"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintStart_toStartOf="parent"/>

    </ConstraintSet>

    <ConstraintSet android:id="@+id/wave_end">
        <Constraint
            android:id="@+id/btn_one"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>
</MotionScene>

Motion Scene Two

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        android:id="@+id/transition_straight"
        motion:constraintSetEnd="@+id/right_end"
        motion:constraintSetStart="@+id/left_start"
        motion:duration="2000"
        motion:motionInterpolator="linear" >
        <OnClick
            motion:targetId="@+id/btn_two"
            motion:clickAction="toggle"/>
    </Transition>

    <ConstraintSet android:id="@+id/left_start">
        <Constraint
            android:id="@+id/btn_two"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            android:layout_marginBottom="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/right_end">
        <Constraint
            android:id="@+id/btn_two"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent" />
    </ConstraintSet>
</MotionScene>

This is the only XML solution I could come up with.

Shawn
  • 798
  • 9
  • 28