Search code examples
androidandroid-motionlayout

MotionLayout - one transition disabling another


I have two transitions in one MotionScene:

<Transition
        android:id="@+id/swipeRightTransition"
        app:constraintSetEnd="@id/swipedRight"
        app:constraintSetStart="@+id/defaultPosition" >

        <OnSwipe
            app:maxAcceleration="60"
            app:dragDirection="dragRight"
            app:onTouchUp="autoComplete"
            app:touchAnchorId="@id/pieChart"
            app:touchAnchorSide="right"/>

    </Transition>

    <Transition
        android:id="@+id/swipeLeftTransition"
        app:constraintSetEnd="@id/swipedLeft"
        app:constraintSetStart="@+id/defaultPosition" >

        <OnSwipe
            app:maxAcceleration="60"
            app:dragDirection="dragLeft"
            app:onTouchUp="autoComplete"
            app:touchAnchorId="@id/pieChart"
            app:touchAnchorSide="left"/>

    </Transition>

If you disable the first transition "swipeRightTransition" with getTransition(R.id.swipeRightTransition).setEnable(false), the second will be disabled too! And setting "setEnable(true)" to the second has no effect, it will be disabled anyway. If you will disable the second transtion "swipeLeftTransition" the first transition works fine. I don't understand it at all.

Full scene code:

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

    <ConstraintSet android:id="@+id/defaultPosition">
        <Constraint android:id="@+id/pieChart"
            android:layout_width="0dp"
            android:layout_height="220dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@id/leftArrowLayout"
            app:layout_constraintEnd_toStartOf="@id/rightArrowLayout"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_gravity="center"/>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/swipedLeft">
        <Constraint android:id="@+id/pieChart"
            android:layout_width="220dp"
            android:layout_height="220dp"
            app:layout_constraintEnd_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/swipedRight">
        <Constraint android:id="@+id/pieChart"
            android:layout_width="220dp"
            android:layout_height="220dp"
            app:layout_constraintStart_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    </ConstraintSet>

    <Transition
        android:id="@+id/swipeRightTransition"
        app:constraintSetEnd="@id/swipedRight"
        app:constraintSetStart="@+id/defaultPosition" >

        <OnSwipe
            app:maxAcceleration="60"
            app:dragDirection="dragRight"
            app:onTouchUp="autoComplete"
            app:touchAnchorId="@id/pieChart"
            app:touchAnchorSide="right"/>

    </Transition>

    <Transition
        android:id="@+id/swipeLeftTransition"
        app:constraintSetEnd="@id/swipedLeft"
        app:constraintSetStart="@+id/defaultPosition" >

        <OnSwipe
            app:maxAcceleration="60"
            app:dragDirection="dragLeft"
            app:onTouchUp="autoComplete"
            app:touchAnchorId="@id/pieChart"
            app:touchAnchorSide="left"/>

    </Transition>
</MotionScene>

Please help!


Solution

  • This is a bug/feature.

    The first transition is the default transition. So at the start you are on that transition. Which gets disabled. So it cannot switch to the other transition because you are stuck on a transition that is disabled. The simple solution is to set the other transition at the same time.

    so:

    ml.setTransition(R.id.swipeLeftTransition);
    ml.getTransition(R.id.swipeRightTransition).setEnable(false)
    

    Testing with this:

    <?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/sLeft"
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/left">
        <OnSwipe
            motion:touchAnchorId="@id/view"
            motion:dragDirection="dragLeft" />
    </Transition>
    <Transition
        android:id="@+id/sRight"
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/right">
        <OnSwipe
            motion:touchAnchorId="@id/view"
            motion:dragDirection="dragRight" />
    </Transition>
    
    <ConstraintSet android:id="@+id/start">
    
    </ConstraintSet>
    
    <ConstraintSet android:id="@+id/left">
    
        <Constraint
            android:id="@+id/view"
            android:layout_width="64dp"
            android:layout_height="64dp"
    
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintBottom_toBottomOf="parent"/>
    
    </ConstraintSet>
    
    <ConstraintSet android:id="@+id/right">
    
        <Constraint
            android:id="@+id/view"
            android:layout_width="64dp"
            android:layout_height="64dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
    
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintBottom_toBottomOf="parent"/>
    
    </ConstraintSet>
    

    If I call

         onAttachedToWindow() {
        super.onAttachedToWindow();
         
        motionLayout.setTransition(R.id.sRight);
        motionLayout.getTransition(R.id.sLeft).setEnable(false);
    }
    

    I can only swipe right

    The only other problem is if you are in the "left" state you are you are stuck