Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible use motion layout with different transitions?

Tags:

android

I'm trying to show one view in different places depending on which button was clicked. But MotionScene not working when I'm using two in it.

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

<Transition android:id="@+id/toTimePicker2"
motion:duration="500" motion:constraintSetStart="@layout/add_event_fragment" 
 motion:constraintSetEnd="@id/enableTimePicker2">
<OnClick motion:target="@+id/time_to" motion:mode="toggle"/>
</Transition>

<Transition android:id="@+id/toTimePicker1"
motion:constraintSetStart="@layout/add_event_fragment" 
motion:constraintSetEnd="@id/enableTimePicker1"
motion:duration="500">
<OnClick motion:target="@+id/time_from"
  motion:mode="toggle" />
 < /Transition >

Does anyone have an idea how to implement it with motion layout? Looks like I should use ConstraintSet in code, but I just want to know is this possible with Motion or not

like image 924
Slava Krasnov Avatar asked Oct 24 '18 14:10

Slava Krasnov


2 Answers

After hours and hours of trying different things, I finally found out why it wasn't working for me. I knew it must be possible because google provides a sample that has multiple transitions https://github.com/googlesamples/android-ConstraintLayoutExamples/blob/multi_state/motionlayout/src/main/res/xml/scene_26.xml. But no matter what I tried, only the first transition in the xml file would work. What I finally realized, is that in order for a transition to work it, the current state of the UI must match the begin or end state of the transition as defined in the constraint set. Not only that, but you can't have the same constraint set defined more than once, meaning if you have two different transitions that can happen on the initial screen, both transitions need to share the constraint set.

I created a simple example of two buttons that move with different translations. I couldn't find a simple example of this anywhere so hopefully this will help some people. As you'll see in the video, when the left to right text has moved to the right, you can't move the top to bottom text to the bottom because that state was not defined in a transition.

Finally, the last gotcha I encountered is every constraint set seems to have to contain every view that is part of a transition, regardless of whether it is in the current transition. Otherwise views just seem to move at random.

enter image description here

Here is the layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:showIn="@layout/activity_main"
        app:layoutDescription="@xml/motion_scene"
        tools:context=".MainActivity">

    <TextView
            android:id="@+id/left_to_right_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Left to right"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

    <TextView
            android:id="@+id/top_to_bottom_text"
            android:text="Top to bottom"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

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

And this is the MotionScene

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


    <Transition
            app:constraintSetStart="@id/base"
            app:constraintSetEnd="@id/bottom">
        <OnClick
                app:targetId="@id/top_to_bottom_text">

        </OnClick>

    </Transition>

    <Transition
            app:constraintSetStart="@id/base"
            app:constraintSetEnd="@id/right">
        <OnClick
                app:targetId="@id/left_to_right_text">

        </OnClick>

    </Transition>


    <ConstraintSet android:id="@+id/base">

        <Constraint
                android:id="@id/left_to_right_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>

        <Constraint
                android:id="@id/top_to_bottom_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/bottom">

        <Constraint
                android:id="@id/left_to_right_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>

        <Constraint
                android:id="@id/top_to_bottom_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
        />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/right">

        <Constraint
                android:id="@id/left_to_right_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>

        <Constraint
                android:id="@id/top_to_bottom_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>
    </ConstraintSet>
</MotionScene>
like image 102
odiggity Avatar answered Nov 07 '22 16:11

odiggity


I faced a similar issue wherein I had defined 2 transitions: A -> B (will refer as transition X) B -> C (will refer as transition Y) both triggered on clicking the animated view.

It was the order of transitions in the motion scene file that mattered in my case. Whichever transition was defined first would get executed first. So, if transition Y was defined above transition X, then only B -> C -> B transitions were possible. However, on placing transition X above transition Y in the motion scene file, following transitions became possible - A -> B -> C -> B.

Note: A -> B could still only be performed once.

like image 27
Rishabh Sharma Avatar answered Nov 07 '22 17:11

Rishabh Sharma