mf

Creating Animations With MotionLayout for Android

Thanks to its remarkable versatility, the ConstraintLayout widget has become the “Swiss Army knife” of layouts for Android app developers. However, adding complex animations to its contents, although possible, can be quite time-consuming. That’s why Google introduced the MotionLayout widget in I/O 2018.

The MotionLayout widget, which is now a part of Android’s support library, extends the ConstraintLayout widget. It is a unique widget that allows you to animate its contents declaratively using just XML. Furthermore, it offers fine-grained control over all its animations.

In this tutorial, I’ll show you how to add it to your Android Studio projects and create a few different animations with it.

Prerequisites

To follow this tutorial, you’ll need:

  • Android Studio 3.1.3 or higher
  • a device or emulator running Android API level 21 or higher
  • a basic understanding of the ConstraintLayout widget

1. Add Dependencies

To be able to use the MotionLayout widget in your Android Studio project, you must have the latest version of the Constraint Layout support library as an implementation dependency. Additionally, in order to avoid version conflicts, make sure you include a dependency for the latest stable version of the v7 appcompat support library.

Accordingly, add the following code to the app module’s build.gradle file:

2. Define a Layout

The MotionLayout widget can do everything the ConstraintLayout widget can. Therefore, you can freely replace any instance of the latter with the former. For now, however, I suggest you create a new layout XML file and add the MotionLayout widget to it as the root element.

Throughout this tutorial, we’ll be animating an ImageView widget. So add it as the first child of the layout.

You’re free to use any drawable as the source of the ImageView widget. In the above code, I’m using a color drawable.

Next, add a button you can press to start the animations. The following code shows you how to position it in the center of the layout:

Additionally, to monitor the progress of the animations, add a SeekBar widget to the layout and position it below the button. Here’s how:

Lastly, because there’s an on-click event handler associated with the button, make sure you define it in your activity.

3. Create a Motion Scene

You may have noticed that we did not add any constraints to the ImageView widget while defining the layout. That’s because we’ll be adding them to a motion scene instead. A motion scene is an XML file that contains details about the animation you want to create with a MotionLayout widget.

To create a new motion scene, create an XML resource file and add a MotionScene element to it.

A motion scene contains ConstraintSet elements specifying the constraints that must be applied to a widget at different points in the animation. Motion scene files usually contain two constraint sets: one for the beginning of the animation and one for the end.

The following code shows you how to create two constraint sets that will help the MotionLayout widget move the ImageView widget from the bottom right corner of the screen to the top left corner:

Note that each ConstraintSet element must always specify both the desired position and the desired size. This is important because it will overwrite any previously set layout information.

To help the MotionLayout widget understand the order in which the constraint sets must be applied, you must next create a Transition element. By using its intuitively named constraintSetStart and constraintSetEnd attributes, you can specify which set must be applied first and which last. The Transition element also allows you to specify the duration of the animation.

At this point, the motion scene is complete. However, the MotionLayout widget is still not aware of it. So go back to the layout XML file, add a layoutDescription attribute to the widget, and set its value to the name of the motion scene file.

If the name of your motion scene file is my_scene.xml, your MotionLayout widget should now look like this:

4. Start the Animation

When you run the app, the MotionLayout widget will automatically apply the constraint set specified in the constraintSetStart attribute of the Transition element. Therefore, to start the animation, all you need to do is call the transitionToEnd() method of the widget. The following code, which must be added to the on-click event handler you created in an earlier step, shows you how:

At this point, if you run the app and press the button, you should be able to see the ImageView widget smoothly move across the screen.

 

5. Handle Animation Events

By attaching a TransitionListener object to the MotionLayout widget, you can closely monitor the progress of the animation.

The TransitionListener interface has two abstract methods, and Android Studio will automatically generate stubs for them.

The onTransitionCompleted() method is called when a transition from one constraint set to another is complete. For now, let’s use it to reset the constraints of the ImageView widget by calling the transitionToStart() method inside it.

The onTransitionChange() method is called every time the progress of the animation changes. As such, the progress is a floating-point number that lies between zero and one. The following code shows you how to update the SeekBar based on the progress of the animation:

Go ahead and run the app again to see two animations now.

 

6. Create Key Frames

In our animation, the ImageView widget moves in a path that looks like a straight line. That’s because the MotionLayout widget is given only two points to work with: the starting point, which is at the bottom right corner of the screen, and the ending point, which is at the top left corner of the screen. If you want to alter the shape of the path, you’ll have to provide a few intermediate points, which lie between the starting and ending points. To do so, you’ll have to create new key frames.

Before you start creating key frames though, you must add a KeyFrameSet element to the Transition element of your motion scene. Inside the new element, you are free to create any number of key frames.

The MotionLayout widget supports many different types of key frames. In this tutorial, we’ll be working with only two types: KeyPosition frames and KeyCycle frames.

KeyPosition frames are the ones that help you alter the shape of the path. While creating them, make sure you provide the ID of the target widget, a position along the timeline, which can be any number between 0 and 100, and the desired X or Y coordinates specified as a percentage. The coordinates can either be relative to the actual X or Y axes or be relative to the path itself.

The following code shows you how to create two key frames that force the ImageView widget to follow a path that avoids collisions with the button and the seek bar:

If you run the app now, you should see an animation that looks like this:

 

You are, of course, free to add more key frames. For example, by adding the following key frame towards the end of the timeline, you can make the ImageView widget follow a more wavy path:

By using a KeyCycle frame along with the KeyPosition frames, you can add oscillations to the animation. While creating it, you must again provide the ID of the target widget, a position along the timeline, and the desired value of the property that has to oscillate back and forth. Additionally, you must configure an oscillator by providing details such as the wave shape to use and the wave period.

The following code creates a KeyCycle frame that uses a sine-wave oscillator to periodically rotate the ImageView widget by 50 degrees:

On running the app again, you should see an animation that looks like this:

 

7. Make Animated Widgets Interactive

All this while, you’ve been pressing a button to start the animation. Such a button, however, is not always necessary because the MotionLayout widget allows you to directly attach touch event handlers to the widgets being animated. Currently, it supports the on-click and the on-swipe events. 

For instance, you can add the following OnClick element, which targets the ImageView widget, inside the Transition element of your motion scene to make the button redundant:

Similarly, you can use an OnSwipe element to allow the user to manually drag the ImageView widget across the screen. While creating the element, you must make sure you provide the right drag direction and the side of the widget that should act as the drag handle.

If you run the app again, you should now be able to drag the ImageView widget.

 

Conclusion

You now know how to use the MotionLayout widget to quickly add complex, interactive animations to your Android apps. You can be sure that the animations will run without any lag or jitter on most devices, so long as you avoid nested views.

It’s worth noting that upcoming releases of Android Studio will include a visual Motion Editor, which is likely to further improve the usability of the widget.

To learn more, do refer to the official documentation.

Powered by WPeMatico

Leave a Comment

Scroll to Top