Introduction to MotionLayout (part II)

Nicolas Roard
Jun 27, 2018 · 5 min read

This is part II of a series of articles introducing MotionLayout. If you haven’t yet, please check part I !

In this article, we will continue covering basic MotionLayout features through various examples, introducing custom attribute interpolation, image operations and keyframes.

Example 03 : Custom attribute

Indeed, originally ConstraintSet only encapsulated the layout rules; but for richer animations, we often need to transition other things (for example, a background color). In ConstraintLayout 2.0, ConstraintSet can also store custom attribute states. Let’s say we want the following motion, where our view’s background will change color:

Previously, you would have had to handle this in code. Now, you can instead specify the attribute directly in XML:

<Constraint
android:id="@+id/button" ...>
<CustomAttribute
motion:attributeName="backgroundColor"
motion:customColorValue="#D81B60"/>
</Constraint>

Here’s the modified MotionScene file for the above animation:

CustomAttribute are specified with the attributeName, which needs to match the getter/setter methods of an object such that:

  • getter: getName (e.g. getBackgroundColor)
  • setter: setName (e.g. setBackgroundColor)

The value type also needs to be specified:

  • customColorValue
  • customIntegerValue
  • customFloatValue
  • customStringValue
  • customDimension
  • customBoolean

Lastly, when defining a custom attribute, you do need to define it both in the start and the end ConstraintSet.

Example 04 : ImageFilterView (1/2)

Let’s do for example a simple cross-fade between two images, such as:

We first need to create a MotionLayout file with the image:

The main difference from a normal ImageView here is the altSrc attribute:

<android.support.constraint.image.ImageFilterView
android:id="@+id/image"
...
android:src="@drawable/roard"
app:altSrc="@drawable/hoford"/>

The MotionScene file will simply apply a custom attribute on the crossfade property:

Example 05 : ImageFilterView (2/2)

saturation : 0 = grayscale, 1 = original, 2 = hyper saturated

contrast : 1 = unchanged, 0 = gray, 2 = high contrast

warmth : 1 = neutral, 2 = warm (red tint), 0.5 = cold (blue tint)

crossfade (with app:altSrc)

Here’s another example showing how to play with an image saturation:

Specifying the saturation can be done simply by using a custom attribute:

<CustomAttribute
motion:attributeName="saturation"
motion:customFloatValue="1" />

Here’s the MotionLayout file we use in this example:

And here’s the corresponding scene file:

Keyframes

In some situations, you may want to have an intermediate state — a state to go through, but not a state to stay in. You could specify more than two ConstraintSets, but a more lightweight approach is to use Keyframes.

Keyframes can be applied to position or to attribute values; they basically let you specify a change at a point in time during the transition.

For example, you may want to say that at 25% of the transition, the widget should turn red. Or that at 50% of the transition, the widget should move up.

Example 06 : Keyframe (1/2), position

As a quick introduction to position keyframes, here’s how you would specify an intermediate position happening at 50% of the total transition, positioned 25% of the screen:

<Transition ...>
<KeyFrameSet>
<KeyPosition
motion:keyPositionType="parentRelative"
motion:percentY="0.25"
motion:framePosition="50"
motion:target="@+id/button"/>
</KeyFrameSet>
</Transition>

The resulting motion will be:

As usual, the MotionLayout file itself is pretty simple:

The MotionScene file is very similar to the previous ones we already saw, with the addition to a KeyPosition element:

Example 07 : Keyframe (2/2), attribute

For example, we may want to specify the scale and rotation of the object we are manipulating at the same 50% position to get the following transition:

This can be achieved by adding a KeyAttribute element in the KeyFrameSet:

<KeyFrameSet>
<KeyAttribute
android:scaleX="2"
android:scaleY="2"
android:rotation="-45"
motion:framePosition="50"
motion:target="@id/button" />
</KeyFrameSet>

The MotionLayout file is the same as in the previous example, and the only difference in the MotionScene file is adding the KeyAttribute:

Conclusion

You can find the source code for those examples in the ConstraintLayout examples github repository.

There’s a lot more covered in this series of articles:

  • Introduction to MotionLayout (part I)
  • Custom attributes, image transitions, keyframes (part II)
  • Taking advantage of MotionLayout in your existing layouts (CoordinatorLayout, DrawerLayout, ViewPager) (part III)
  • All about Keyframes! (part IV)
  • MotionLayout as a choreographer of root layout
  • Nesting MotionLayout & other Views
  • MotionLayout with fragments

Feedback, feature request, bug reports? please file them on the android issue tracker.

More info on ConstraintLayout & MotionLayout ? Follow us on twitter, @camaelon and @johnhoford

Google Developers

Engineering and technology articles for developers, written…

Google Developers

Engineering and technology articles for developers, written and curated by Googlers. The views expressed are those of the authors and don't necessarily reflect those of Google.

Nicolas Roard

Written by

I’m working on Android stuff at Google

Google Developers

Engineering and technology articles for developers, written and curated by Googlers. The views expressed are those of the authors and don't necessarily reflect those of Google.