Introduction to MotionLayout (part II)

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

In part I we last created a MotionLayout with a self-contained MotionScene. We can take advantage of this to specify transition on attributes that are not related to the position only.

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)

When dealing with complex transitions, there’s often the need to do some operations on images, and animating them. ConstraintLayout 2.0 brings a small utility class called ImageFilterView (which is a subclass to AppCompatImageView) to easily allow this.

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)

ImageFilterView offers more capabilities:

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

The general idea for MotionLayout is that “resting states” are implemented as ConstraintSets. This way, we know that the resulting layouts will correctly adapt to different screen sizes: essentially, MotionLayout will behave like a typical ConstraintLayout.

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

There are several ways (pathRelative, deltaRelative, parentRelative) you can set up a position keyframe (KeyPosition), which we will cover in detail in part IV of this series.

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

In a similar manner to position keyframes, you can specify an attribute value at a specific point in the transition (using KeyAttribute).

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

This second article covers more advanced functionalities of MotionLayout, giving examples of how to take advantage of custom attributes and keyframes to create more compelling animations.

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