Skip to content

ViewTransition

Nicolas Roard edited this page Jul 31, 2021 · 10 revisions

ViewTransition is a new tag that let you specify single view animations within MotionLayout. This allows you to handle complex animation and interactions without having to define all the possible combinations as ConstraintSets.

For example, imagine that you have a 3x3 keypad, and you want to animate each individual button of the keypad when they are clicked upon. Before ViewTransition, you would need to create 10 separate ConstraintSets (one for all buttons at rest, and one for each button animating), also repeating a similar animation 9 times. And of course, that's in the case where you would be happy with only having one button animating at a time; if you wanted more complex animation patterns (say, two or more buttons could be animating simultaneously), the number of combinations would quickly explode.

Instead, using ViewTransition you can define a single generic animation for how you would want the button to animate (say, it tilts), and then run it on a specific view, essentially letting you apply this animation on top of the existing state.

It also can be a great way of reusing specific animations (see MotionEffect on how you can take advantage of ViewTransition with it).

The attributes

 <ViewTransition
        android:id="@+id/spin_equ"
        motion:motionTarget="@+id/button10"
        motion:viewTransitionMode="noState"
        motion:onStateTransition="actionDown"
        motion:duration="600"
        motion:pathMotionArc="none"
        motion:motionInterpolator="linear"
        motion:setsTag="@id/sets_tag_on_done"
        motion:clearsTag="@id/clears_tag_on_done"
        motion:ifTagSet="@id/only_run_if_set"
        motion:ifTagNotSet="@id/only_run_if_not_set"
      >
     <ConstraintOverride ....> 
       <CustomAttribute ...\>
     </ConstraintOverride>
    
    <KeyFrameSet>
         ...
    </KeyFrameSet>
  </ViewTransition>
  • id is used for invoking a View Transition with motionLayout.viewTransition(id, view...)
  • motionTarget may be used to define the view or collection of views in conjunction with layout_constraintTag
  • viewTransitionMode defines 3 major modes of ViewTransition currentState, allStates and noState. (noState runs asynchronously per view)
  • onStateTransition allows the ViewTransition on actionDown or actionUp
  • duration duration of the transition in milliseconds (same as <Transition>)
  • transitionDisable allows you to have disabled ViewTransitions which can be enabled with motionLayout.enableViewTransition(id)
  • pathMotionArc views move in quarter ellipses (same as )
  • motionInterpolator defines how the transition will animate easing (same as )
  • setsTag on completion of a ViewTransition on a view it calls view.setTag(id, System.nanoTime)
  • clearsTag on completion of a ViewTransition on a view it calls view.setTag(id, null)
  • ifTagSet ViewTransition will not run if view.getTag(id) == null
  • ifTagNotSet ViewTransition will not run if view.getTag(id) != null

The below examples and many more can be found in this layout and MotionScene

Running a View Transition

There are 3 ways to run a viewTransition

  1. The view transition fires itself using motion:onStateTransition=".."
  2. KeyTrigger can launch a view transition (allowing objects to react to hitting a point during progress or collision)
  3. Launch programmatically

Launching a View transition from code.

MotionLayout has a few API's for working with ViewTransition

     // Execute a ViewTransition.
     // Transition will execute if its conditions are met and it is enabled
    public void viewTransition(int viewTransitionId, View... view) {  }

    //Enable a ViewTransition ID.
    public void enableViewTransition(int viewTransitionId, boolean enable) { }

    // Is transition id enabled or disabled 
    public boolean isViewTransitionEnabled(int viewTransitionId) { }
  
    // Apply the view transitions keyFrames to the MotionController.
    // Note ConstraintOverride is not used
    public boolean applyViewTransition(int viewTransitionId, MotionController motionController) { }

View Transitions allow you to separate the action from the animation. For example if you setVisibility(invisible) it will instantly be removed from the screen having a transition allows the motion designer the ability to animate the removal.

Example 1 Simple Popup

    <ViewTransition
        android:id="@+id/pop"
        motion:onStateTransition="actionDownUp"
        motion:motionTarget="@+id/button1"
        motion:viewTransitionMode="noState"
        motion:duration="300">
        <KeyFrameSet>
            <KeyAttribute
                motion:framePosition="100"
                android:scaleX="1.5"
                android:scaleY="1.5"
                />
        </KeyFrameSet>
    </ViewTransition>

This scales the button up when pressed and collapses it when released.

vt_upDown

Example 2 Fancy Pop Button

    <ViewTransition
        android:id="@+id/bigPop2"
        motion:onStateTransition="actionDownUp"
        motion:motionTarget="@+id/button15"
        motion:viewTransitionMode="noState"
        motion:duration="3000"
        motion:upDuration="300"
        >

        <KeyFrameSet>

            <KeyAttribute
                motion:framePosition="100"
                android:scaleX="3"
                android:scaleY="3"
                />
            <KeyTimeCycle
                motion:framePosition="0"
                motion:wavePeriod="4"
                android:rotation ="0"
                />
            <KeyTimeCycle
                motion:framePosition="80"
                motion:wavePeriod="4"
                android:rotation ="0"
                />
            <KeyTimeCycle
                motion:framePosition="99"
                motion:wavePeriod="4"
                android:rotation ="20"
                />

        </KeyFrameSet>
    </ViewTransition>

More elaborate popup with shake button if you long press

vt_shake

Example 3 Removes the button for the current state

    <ViewTransition
        android:id="@+id/gone"
        motion:onStateTransition="actionUp"
        motion:motionTarget="@+id/button3"
        motion:viewTransitionMode="currentState"
        motion:duration="300">
        <ConstraintOverride android:visibility="gone"/>
    </ViewTransition>