Animations in Android
  • Introduction
  • About us
  • Basic animations
  • ConstraintLayout: Core concepts
  • I like to move it, move it!
  • Step 1
  • Step 2
  • Step 2: Solution
  • Step 3
  • Step 3: Solution
  • Step 4
  • Step 4: Solution
  • Step 5
  • Step 5: Solution
  • Step 6
  • Step 7
  • Step 7: Solution
  • Step 8
  • Step 8: Solution
  • MotionLayout
  • Party time!
  • Shared element transition
  • Adding a RecyclerView
  • Activity transitions
  • Adding a second Activity
  • Adding the shared element transition
  • You made it!
  • VectorDrawable
  • VectorDrawable: Solution
  • Using the VectorDrawable
  • RecyclerView item animation & self-contained MotionScene
  • Creating a self-contained MotionScene
  • Creating a self-contained MotionScene : Solution
  • Adding animations in the RecyclerView items: Step 1
  • Adding animations in the RecyclerView items: Step 2
  • RecyclerView animations step 2: Solution
  • Physic based animations
  • Implement a spring animation
  • Spring animation: Solution
  • The finish line!
Powered by GitBook
On this page
  • MotionScene
  • Switching to a MotionLayout
  • Creating the MotionScene
  • Connecting the dots
  • OOPS!

MotionLayout

A MotionLayout is a ConstraintLayout which allows you to animate layouts between various states. MotionLayout links to and requires a MotionScene file.

MotionScene

A MotionScene file can contain all that is needed for specifying the animation:

  • the ConstraintSets used

  • the transition between those ConstraintSets

  • keyframes, touch handling, etc.

A ConstraintSetlets you create and save constraints, and apply them to an existing ConstraintLayout

Motion scene files usually contain two constraint sets: one for the beginning of the animation and one for the end.

Make sure that the ConstraintLayout import version is at least ConstraintLayout 2.0.0-alpha1.

Switching to a MotionLayout

The MotionLayout is a subclass of ConstraintLayout. So to transform a ConstraintLayout to a MotionLayout we need to only replace the class name from :

<android.support.constraint.ConstraintLayout .../>

to :

<android.support.constraint.motion.MotionLayout .../>

Creating the MotionScene

To create our MotionScene we first need to create an XML directory in our resources file. Then we create a new XML file, called motion_scene_main.xml

Our MotionScene should contain a transition attribute where we will specify the starting and ending constraints, how long it should last and we are also going to add a gesture handler.

motion_scene_main.xml
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto">
    <Transition
        app:constraintSetEnd="@layout/activity_main_end"
        app:constraintSetStart="@layout/activity_main_start"
        app:duration="1000">

        <OnSwipe
            app:dragDirection="dragUp"
            app:touchAnchorId= "@id/second_bg"
            app:touchAnchorSide="top" />
    </Transition>
</MotionScene>

Connecting the dots

As we mentioned above, the MotionLayout links to the MotionScene. But right now our MotionLayout is still not aware that we created that file. So we need to go back to the activity_main_start.xml file, add a layoutDescription attribute to the widget, and set its value to the name of the motion scene file.

activity_main_start.xml
<android.support.constraint.motion.MotionLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="@color/colorBgDark"
    app:layoutDescription="@xml/motion_scene_main">
    
    ....
    
</android.support.constraint.motion.MotionLayout>

OOPS!

If we now try to enter the design mode of that layout we will see that it cannot render. The reason for this is that all the widgets found in the starting constraint should also be included to the ending one and vice versa. So we need to copy paste the views we haven't added so far to both of our layouts.

activity_main_start.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="@color/colorBgDark"
    app:layoutDescription="@xml/motion_scene_main">

    <!-- Circle ImageView --> 
    <!-- Main ImageView --> 
    <!-- CardView --> 
    <!-- ImageView Paw 1--> 
    <!-- ImageView Paw 2--> 
    <!-- ImageView Paw 3--> 
    <!-- ImageView Paw 4--> 
    <!-- ImageView Paw 1--> 
    <!-- Second Background View--> 

    <ImageView
        android:id="@+id/iv_leaf_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="28dp"
        android:layout_marginBottom="150dp"
        android:rotation="80"
        android:src="@drawable/ic_leaf"
        app:layout_constraintBottom_toBottomOf="@+id/guideline_horizontal20"
        app:layout_constraintEnd_toEndOf="@+id/guideline_verticalHalf"
        tools:ignore="ContentDescription" />

    <ImageView
        android:id="@+id/iv_leaf_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="136dp"
        android:layout_marginBottom="150dp"
        android:rotation="15"
        android:src="@drawable/ic_leaf"
        app:layout_constraintBottom_toBottomOf="@+id/guideline_horizontal20"
        app:layout_constraintEnd_toEndOf="parent"
        tools:ignore="ContentDescription" />

    <!-- Guidelines --> 

</android.support.constraint.motion.MotionLayout>
activity_main_end.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorBgDark"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- Circle ImageView -->
    <!-- ImageView Leaf 1-->
    <!-- ImageView Leaf 2-->
    <!-- ImageView Leaf 1-->
    <!-- CardView-->

    <ImageView
        android:id="@+id/iv_main"
        android:layout_width="180dp"
        android:layout_height="180dp"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:scaleType="centerInside"
        android:src="@drawable/alex"
        app:layout_constraintBottom_toBottomOf="@+id/second_bg"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.343"
        tools:ignore="ContentDescription" />

    <ImageView
        android:id="@+id/iv_paw_1"
        android:layout_width="65dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="88dp"
        android:rotation="30"
        android:src="@drawable/ic_paw"
        app:layout_constraintStart_toStartOf="@+id/iv_main"
        app:layout_constraintTop_toTopOf="@id/iv_main"
        tools:ignore="ContentDescription" />

    <ImageView
        android:id="@+id/iv_paw_2"
        android:layout_width="65dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="112dp"
        android:layout_marginTop="56dp"
        android:rotation="45"
        android:src="@drawable/ic_paw"
        app:layout_constraintStart_toStartOf="@+id/iv_main"
        app:layout_constraintTop_toTopOf="@id/iv_main"
        tools:ignore="ContentDescription" />

    <ImageView
        android:id="@+id/iv_paw_3"
        android:layout_width="65dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="92dp"
        android:rotation="-30"
        android:src="@drawable/ic_paw"
        app:layout_constraintEnd_toEndOf="@+id/iv_main"
        app:layout_constraintTop_toTopOf="@id/iv_main"
        tools:ignore="ContentDescription" />

    <ImageView
        android:id="@+id/iv_paw_4"
        android:layout_width="65dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="56dp"
        android:layout_marginEnd="104dp"
        android:rotation="-45"
        android:src="@drawable/ic_paw"
        app:layout_constraintEnd_toEndOf="@+id/iv_main"
        app:layout_constraintTop_toTopOf="@id/iv_main"
        tools:ignore="ContentDescription" />

    <!-- Second Background View --> 
    <!-- Guidelines --> 

</android.support.constraint.motion.MotionLayout>
PreviousStep 8: SolutionNextParty time!

Last updated 6 years ago

If you want to learn more about the gesture handlers check the documentation .

here