Android Studio 4.0 will include a lot of really great features, like layout Multi Preview, support for Jetpack Compose or Live Layout Debug tool. This seems to be a lot for a single release, but there is also one more thing - MotionEditor. This tool finally makes working with MotionLayout really easy and fun!
MotionLayout is out there since the release of constraint-layout:2.0.0-alpha1
(June 2018), and it has already caused quite a stir. When we first saw the example animations that can be done pretty easily using it, we were pretty impressed. However, as it turned out, using MotionLayout was time- and work-consuming, because there was a lot of code to write, and in order to test it we had to run our app on the device each time.
These times are over!
As for constraint-layout:2.0.0-beta3
and Android Studio 4.0 Canary1 we can edit MotionLayout in the graphic design tool, and what’s even better, we can preview the effects of our work right in the Android Studio, with no need to run the app on the device ❤
That sounds really awesome. Now, let’s see how it works.
MotionLayout
At the beginning, just a few words about the MotionLayout itself.
MotionLayout
class extends ConstraintLayout
. That means you can seamlessly convert the latter to the first, and without any changes, it should work pretty much the same. That is really nice, because it enables us to experiment with MotionLayout, starting with any existing ConstraintLayout.
<androidx.constraintlayout.widget.ConstraintLayout 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">
<View
android:id="@+id/sky"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/sky_morning"
app:layout_constraintBottom_toTopOf="@id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/ground"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/ground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/guideline" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<ImageView
android:id="@+id/biker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/biker"
android:src="@drawable/ic_bike"
app:layout_constraintBottom_toBottomOf="@id/guideline"
app:layout_constraintTop_toTopOf="@id/guideline" />
</androidx.constraintlayout.widget.ConstraintLayout>
The real magic of MotionLayout lays in the MotionScene resource file, which contains all the constraints and attributes transitions that result in our layout animation.
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/start">
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
</ConstraintSet>
</MotionScene>
Each Transition has to have a start and end ConstraintSet, and a number of KeyFrames that enables us to achieve various interesting effects. You should remember, that constraints set in the MotionScene always take precedence over these declared in the MotionLayout file.
If you want to know more about the MotionLayout itself, there is a great series of articles on the Google Developers Medium.
To use all the discussed below features you need to add a dependency to your build.gradle
file.
dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta3'
}
MotionEditor
Ok, so now that we know what MotionLayout is, let’s see what Android Studio 4.0 can do to make our work with it more enjoyable.
First of all, in the layout design panel there is a tool to automatically convert our selected ConstraintLayout to the MotionLayout.
What it really does is changing the root layout to MotionLayout, creating a new MotionScene xml file in the resources/xml
package and setting the app:layoutDescription
attribute of the new layout to the motion scene file. That’s it. But is also redirects us to the brand new MotionEditor view.
There you can see a preview of our MotionLayout on the left, a panel with all the transitions and constraint sets in the middle, and attributes panel on the right.
One thing to remember is that you can navigate between code, design, and split the screen using the three buttons on the top right corner of the view (not on the bottom left as it was before).
Now, by navigating between the start and end states in the middle panel, we are able to add/change views constraints and attributes. E.g. we want the color of the sky to change from light to dark. All we need to do is to choose start state, click on sky
entry and add a new Custom Attribute (there is an autocomplete in the attributes popups ☺). Then repeat it for the end state.
MotionLayout will do the rest for us, and we get a nice simple sky animation.
In a similar way, but by changing the start and end constraints of the biker
image, we are able to create a changing position animation.
By clicking on the grey arrow between the states, you open the Transition panel where you can play the current motion animation.
To make it work on the device we need to start the motion somehow. We can either start/set the progress in code, or add an OnSwipe/OnClick MotionObject. In this example, we choose the second option, and by clicking the third button on top of the motion panel we add a SwipeHandler with an anchor at the biker.
Now let’s add some sunshine to our animation ☺
We add the sun image, and want it to move above the biker, but on the arc, so simply changing the constrains won’t be sufficient. We need to add also a KeyFrame. We can do it by choosing KeyPosition
from the Transition panel, and setting the percentY
position in a 50th frame (frames go from 0 to 100) to a negative value, and type do pathRelative
.
Now our animation starts to gain some life.
In a similar way, but using KeyAttribute
we can modify things like scale, rotation or alpha of our view.
Let’s get nuts and add all of the above attributes! Making the sun do a 360 degrees rotation during the animation, scaling to 1.5 in the middle, and vanishing after the 60th frame.
When we add a moon image with the same path as the sun image, and with alpha increasing after 60th, we’ll get a really nice transition.
Now you can use your imagination and add other views to the animation. Will you be able to recreate the one from below? ☺
This kind of animation is a great example of how MotionLayout can be mixed with a ViewPager
for creating a really nice custom experience.
You can find the complete code of the example HERE.
It is also worth to mention that if you have a MotionLayout written with an older constraint-layout version and older Android Studio, you can still use it with the Android Studio 4.0, and MotionEditor will work just fine, no changes need to be done ✔
Problems
The tools that Android Studio 4.0 gives us to work with the MotionLayout are great, however we must remember that neither of them is stable yet, and definitely not production-ready. There still can occur some random crashes and other errors.
Here are some problems I encountered while playing with the above example:
• modifying constraints can sometimes cause big lags
• there must be no errors or warnings (!) in your xml code for MotionEditor to work
• ‘showPaths’ option does not work when there are many views in the layout
• MotionEditor does not work for your custom classes extending MotionLayout
Conclusion
Now it’s time for your own experiments. MotionLayout gives us great abilities to create beautiful and meaningful animations. There are many other features that I haven’t discussed here, like multiple transitions in a single MotionScene, creating custom attributes, using MotionLayout progress, KeyCycles, or motion easing.
The best place to start your adventure is definitely the documentation page, where you can find many examples.
If you have any questions regarding the article, or want to share your MotionLayout animations, feel free to leave a comment!
About the Author
Aleksandra Krzemień has profound experience in building all sorts of mobile apps, including those connected with external devices. She is a natural mentor and loves to share her knowledge. Throughout her career, she has been actively engaged in many mentoring programs and IT-related organizations, such as Women in Technology or Google Developers Group. She likes to spend her free time singing and playing board games.