Search code examples
androidkotlinandroid-constraintlayoutandroid-motionlayout

MotionLayout KeyCycle and KeyTimeCycle


I have a Motion layout KeyCycle as -

<KeyFrameSet>
   <KeyCycle
     app:motionTarget="@+id/button"
     app:framePosition="75"
     app:wavePeriod="3"
     app:waveOffset="0dp"
     app:waveShape="triangle"
     android:translationY="50dp" />
</KeyFrameSet>

I just see that my button is shaking from start to end and it does even before frame position is reached. Don't understand what the frame position does here? Also why don't I see a triangular movement?

Also, What is the difference between KeyCycle and KeyTimeCycle?


Solution

  • If only one KeyCycle is created it gets "copied" as a start and an end. (giving you 3)

    You effectively created:

    <KeyFrameSet>
    <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="0"
       app:wavePeriod="3"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="50dp" />
     <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="75"
       app:wavePeriod="3"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="50dp" />
     <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="100"
       app:wavePeriod="3"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="50dp" />
     </KeyFrameSet>
    

    It sound like you want to create a ramp in amplitude :

    <KeyFrameSet>
    <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="0"
       app:wavePeriod="3"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="0dp" />
     <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="75"
       app:wavePeriod="3"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="50dp" />
     <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="100"
       app:wavePeriod="3"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="0dp" />
     </KeyFrameSet>
    

    Or a ramp in frequency:

    <KeyFrameSet>
    <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="0"
       app:wavePeriod="0"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="50dp" />
     <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="75"
       app:wavePeriod="3"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="50dp" />
     <KeyCycle
       app:motionTarget="@+id/button"
       app:framePosition="100"
       app:wavePeriod="0"
       app:waveOffset="0dp"
       app:waveShape="triangle"
       android:translationY="50dp" />
     </KeyFrameSet>
    

    KeyCycle vs. KeyTimeCycle

    An Transition moves a value we call progress from 0.0 to 1.0 KeyCycle is an animation with respect to progress. KeyTimeCycle is cycles in time. If you had a 1 second transition that was linear they would be identical. But with swipe controlled gestures, progress != time as you can stop the progress in the middle. Generally use KeyCycle it is easier to control precisely.

    Short videos on both