Reputation: 233
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
Upvotes: 21
Views: 13650
Reputation: 11
Multiple transitions are supported.
In the code you shared, you have 4 constraint sets, start_home -> end_home, start_search -> end_search. Instead, have only 3 sets, with one being the base state like, start -> end_home and start -> end_search. The 'start' here represents the base state of the screen
This happens because, say you did the home action first and then you did the search action, then the search is not going to work because the starting criteria (start_search) is not going to match the start_home or end_home (which got applied last)
Upvotes: 1
Reputation: 1392
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.
Upvotes: 0
Reputation: 665
A more kotlin'y answer:
with(view as MotionLayout) {
setTransition(R.id.startState, R.id.endState)
transitionToEnd()
}
Upvotes: 1
Reputation: 3484
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.
Upvotes: 0
Reputation: 331
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();//
});
Upvotes: 19