MotionLayout animations for modern Android apps

MotionLayout turns the familiar ConstraintLayout into a state-based animation system. Views can move, resize, fade, rotate, and change visibility as the layout transitions between two carefully defined positions.

This makes MotionLayout suitable for expandable cards, onboarding sequences, detailed panels, and guided actions. Motion stays within the Android view system, so it can respond to touch input and adapt cleanly to different screen sizes.

The following guide covers scene setup, ConstraintSets, transitions, keyframes, accessibility, and testing. The examples use current AndroidX patterns and are designed for teams delivering polished applications to Australian users.

Prepare the layout and dependencies

Add the ConstraintLayout library through Gradle, using a current stable 2.x release:

implementation("androidx.constraintlayout:constraintlayout:2.2.1")

Make MotionLayout the root element of the screen. Its direct children become the views controlled by the animation, while a MotionScene in res/xml defines the states and transitions.

<MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/product_scene"
    app:currentState="@id/collapsed">

    <!-- Product views go here -->

</MotionLayout>

Give every animated view a stable, descriptive ID. Plan the two layouts around the final content rather than treating one state as a simple modification of the other. This is particularly useful for commuters in Sydney and Melbourne, where an animation may need to work one-handed, in portrait mode, and on devices with limited screen space.

Model states with a MotionScene

A MotionScene contains one or more ConstraintSets. Each set describes the position and appearance of a view in a particular state. A product panel might have a collapsed state with hidden details and an expanded state that moves the summary into a header.

A focused ConstraintSet can look like this:

<ConstraintSet
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/collapsed">

    <Constraint
        android:id="@id/summary"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginEnd="24dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <PropertySet android:alpha="0.0" />
        <Transform
            android:scaleX="0.94"
            android:scaleY="0.94" />
    </Constraint>
</ConstraintSet>

Use Constraint attributes for dimensions, margins, and constraints. PropertySet controls properties such as alpha and visibility, while Transform handles scale, rotation, and translation. Avoid changing too many unrelated properties in one transition, as that can make the movement difficult to follow.

Australian apps frequently serve crowded, content-heavy categories, including grocery ordering, telecommunications, transport, and banking. Interfaces inspired by services such as Woolworths, Coles, Telstra, CBA, or NAB benefit from motion that clarifies hierarchy instead of competing with the content.

Connect transitions and gestures

A Transition connects the starting and ending ConstraintSets. Its duration determines how long the interpolation takes, while an interpolator shapes the pace. Values around 250–450 milliseconds usually feel responsive without appearing abrupt.

<Transition
    motion:constraintSetStart="@+id/collapsed"
    motion:constraintSetEnd="@+id/expanded"
    motion:duration="420"
    motion:motionInterpolator="easeInOut" />

For gesture-driven interaction, add OnSwipe inside the transition:

<OnSwipe
    motion:touchAnchorId="@id/handle"
    motion:dragDirection="dragUp"
    motion:onTouchUp="autoComplete" />

The touch anchor can be a visible handle or the view users naturally expect to drag. Restricting the gesture to that element prevents accidental activation during normal scrolling. autoComplete finishes the transition when the finger is released, although applications can also pause at the current progress and wait for a button press.

Motion should preserve familiar Australian conventions. An expandable delivery panel, for example, can reveal a collection window while retaining the country’s common 24-hour clock and DD/MM/YYYY date order. Smooth movement helps users understand where the new information came from without forcing them to relearn the formatting.

Add keyframes and dynamic behaviour

A transition normally interpolates values evenly between its two states. Keyframes let you refine that path by assigning a value at a particular point in the animation. The following example sets the summary to half opacity at 40 percent of the transition:

<KeyFrameSet>
    <KeyAttribute
        motion:motionTarget="@id/summary"
        motion:framePosition="40"
        android:alpha="0.5" />
</KeyFrameSet>

This is useful when a view needs to fade out early and a replacement should appear before the entire layout has settled. Keep keyframes purposeful: several competing movements often make an interface feel busier than a straightforward interpolation.

MotionLayout also provides runtime methods such as transitionToEnd(), transitionToStart(), and setProgress(). Use these when the state depends on a selection, network response, or business rule. A transition listener can then update content after the animation completes, preventing text from changing halfway through a movement.

Accessibility remains essential. Users may reduce or disable system animations, so important information must remain visible without motion, and motion should never be the only signal that a state changed. Since MotionLayout runs locally, it can also deliver smooth feedback for users outside major metropolitan areas or on connections with variable mobile coverage.

Test, polish, and prepare for release

Test each scene on physical devices as well as in Android Studio. Check different screen sizes, display settings, font scales, orientation changes, and devices with modest processing power. Pay particular attention to transitions that combine movement with text resizing, since the final layout may differ from the original ConstraintSet.

The Layout Inspector can reveal missing constraints, conflicting attributes, and unexpected view sizes. When an animation misbehaves, simplify the scene by temporarily removing keyframes and gestures. Confirm that the starting state matches the initial view hierarchy and that every referenced ID exists.

Before release, verify the interaction with touch and accessibility tools, remove decorative motion that delays essential content, and avoid unnecessary resources for effects that can be achieved with transforms and alpha. MotionLayout offers a strong balance between expressive animation and predictable app performance.

Open your next Android project, add one MotionScene for a meaningful state change, test it on a physical handset, and share the finished interaction with your team.