Search code examples
javaandroidkotlinandroid-constraintlayoutandroid-motionlayout

MotionLayout - Single continuous transition on swipe?


I have four different layouts which can be swiped one after another by swiping left.

When a single transition completes, I would like to be able to continue on to another transition upon further swiping left. All layouts have their own transitions when swiping down. What I have currently is a lot of transitions and am setting transitionToState() each time a button is pressed.

Is there a way to achieve this as of now in MotionLayout with just a swipe action? A way to chain transitions into one single transition by swiping left each time.


Solution

  • Short answer is yes if it is not associated with a nestedScrollView (like recycler view).

    In general if you have 3 states A,B & C and two Transitions A->B & B->C with OnSwipe in the same direction in both. They will naturally "chain" I.E. Width touch down in state A it will drag A to B then B to C. Touch up before B and it will stop at B.
    There is no simple way to prevent B being a valid stop.

    More details on onSwipe in this video

    For example this layout file:

    <?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/motionLayout"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="#FF003b60"
      app:layoutDescription="@xml/scene"
      app:motionDebug="SHOW_PATH">
    <View
        android:id="@+id/view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#5F3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
     </androidx.constraintlayout.motion.widget.MotionLayout>
    

    Using MotionScene file:

    <?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
        motion:constraintSetStart="@id/a"
        motion:constraintSetEnd="@+id/b">
        <OnSwipe motion:dragDirection="dragRight" />
      </Transition>
    
      <Transition
        motion:constraintSetStart="@id/b"
        motion:constraintSetEnd="@+id/c">
        <OnSwipe motion:dragDirection="dragRight" />
      </Transition>
    
      <ConstraintSet android:id="@+id/a">
        <ConstraintOverride android:id="@+id/view"
            motion:layout_constraintHorizontal_bias="0" />
      </ConstraintSet>
    
      <ConstraintSet android:id="@+id/b"/>
    
      <ConstraintSet android:id="@+id/c">
        <ConstraintOverride android:id="@id/view"
            motion:layout_constraintHorizontal_bias="1" />
      </ConstraintSet>
      </MotionScene>
    

    This Motion scene has 3 ConstraintSets a,b, & c It also has two transitions a->b and b->c both have on swipes