MotionLayout is a layout class that extends ConstraintLayout.MotionLayoutConstraintLayout
Take for example this subtle animation of a view being scrolled and the profile picture shrinking. Before MotionLayout, this would be a tedious task to complete. We may have needed a CollapsingToolbar and some other custom animation code to ensure the profile picture scales correctly. Now with MotionLayout, this is really easy to achieve with one extra XML file.

In this article, we will be looking at implementing a simple swipe action on a RecyclerView and how we can achieve the scaling animation with MotionLayout.
Add MotionLayout as a Gradle Dependency
To get started with MotionLayout, you need to make sure we have the latest version in your build.gradlefile. (Note: MotionLayout is still in alpha at the time of writing)
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
Create your layout XML as per usual
The great part MotionLayoutConstraintLayoutConstraintLayout (ie barriers, chains etc) is applicable to layouts that we build MotionLayout
To get started, open up your editor and change the root element of your layout to use MotionLayout. Add a RecyclerView and an ImageView to your layout. Make sure the RecyclerView is constrained to the bottom of ImageView

The XML behind the following layout should look similar to this:
<?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" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" app:showPaths="false" app:layoutDescription="@xml/motion_layout_example" android:layout_height="match_parent">
<View android:layout_width="0dp" android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
android:background="@color/colorPrimary"
android:id="@+id/background"
app:layout_constraintBottom_toBottomOf="@id/space"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" android:alpha="0"
/>
<ImageView
android:layout_width="140dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:id="@+id/imageViewAvatar"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
app:layout_constraintDimensionRatio="h,1:1"
app:srcCompat="@drawable/veruca"/>
<TextView
android:text="@string/veruca_salt_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/textViewName"
android:fontFamily="@font/willywonka"
app:layout_constraintStart_toEndOf="@+id/imageViewAvatar"
android:layout_marginStart="16dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:layout_marginTop="8dp"
app:layout_constraintTop_toTopOf="@+id/imageViewAvatar"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/space"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
tools:listitem="@layout/list_item_status"
android:id="@+id/recyclerViewStatus" android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/imageViewAvatar">
</androidx.recyclerview.widget.RecyclerView>
<Space
android:layout_width="0dp"
android:layout_height="8dp"
android:id="@+id/space"
app:layout_constraintStart_toEndOf="@+id/imageViewAvatar"
app:layout_constraintTop_toBottomOf="@id/imageViewAvatar"
app:layout_constraintEnd_toEndOf="@+id/imageViewAvatar"
app:layout_constraintStart_toStartOf="@+id/imageViewAvatar"/>
</androidx.constraintlayout.motion.widget.MotionLayout>
Create the MotionScene XML
In order to animate this layout we need to describe how views should animate in the layout. To do this, create an XML file in xmlmotion_scene.xml
The first thing that we will do, TransitionMotionSceneConstraintSetsTransition
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<Transition
app:constraintSetStart="@id/start"
app:constraintSetEnd="@id/end"
app:duration="1000">
<OnSwipe
app:touchAnchorId="@+id/recyclerViewStatus"
app:touchAnchorSide="top"
app:dragDirection="dragUp" />
</Transition>
<ConstraintSet android:id="@+id/start">
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
</ConstraintSet>
</MotionScene>
The next step, that can be seen in the code snippet above, is to create OnSwipeMotionLayoutdragUp gesture on the touchAnchorIdrecyclerViewStatusdragUp gesture.
In the code snippet above, you may notice that there are ConstraintSetMotionSceneMotionLayout
The first view we want to animate is ImageViewRecyclerViewImageView40dp
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<Transition
app:constraintSetStart="@id/start"
app:constraintSetEnd="@id/end"
app:duration="1000">
<OnSwipe
app:touchAnchorId="@+id/recyclerViewStatus"
app:touchAnchorSide="top"
app:dragDirection="dragUp" />
</Transition>
<ConstraintSet android:id="@+id/start">
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint android:id="@id/imageViewAvatar"
android:layout_width="40dp"
android:layout_height="40dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp">
</Constraint>
</ConstraintSet>
</MotionScene>
Linking the MotionScene to the Layout
In order to link MotionScene to the Layout, you will need to set the property app:layoutDescription="@xml/motion_layout_example" to point to your newly created XML file on the root MotionLayout element.
Running this on RecyclerView , ImageView
Animating Visibility of a View
Now if you wanted to animate the background to go from invisible to visible, we can just add Propertystartend
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<Transition
app:constraintSetStart="@id/start"
app:constraintSetEnd="@id/end"
app:duration="1000">
<OnSwipe
app:touchAnchorId="@+id/recyclerViewStatus"
app:touchAnchorSide="top"
app:dragDirection="dragUp" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint android:id="@id/background">
<PropertySet app:alpha="0"/>
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint android:id="@id/imageViewAvatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp">
</Constraint>
<Constraint android:id="@id/background">
<PropertySet app:alpha="1"/>
</Constraint>
</ConstraintSet>
</MotionScene>
It’s a wrap!

As you can see from the short example above, MotionLayoutMotionLayout, as this article has just touched the surface. Till next time!
Follow me on Twitter – @riggaroo.
