Before diving into details of what additive animations are, here’s a simple showcase to explain why you should use them.

In this sample app (which I totally stole from here), the user taps or drags on the screen to trigger an animation that moves the yellow view towards the finger.

Here’s the normal version using the standard Android animation system (all gifs are downsampled to 30fps):

What changing the animation target usually looks like in Android — ugh!

Notice the abrupt change in velocity when the target changes. When the user glides his finger across the screen, the view doesn’t move at all — the animation is restarted before it has a chance to run!

Here’s the same interaction using additive animations:

Changing animation target with the AdditiveAnimator library.

Additive Animations

In our indoor location application, we periodically recalculate the current position of the user (think of the blue dot indicating your position in Google Maps). Whenever a new position is calculated, we animate the blue dot to the new position — but in Android, this cancels the currently running animation and starts a new one, resulting in disjointed movement!

Having implemented this feature on iOS without any problems (because every UIView -based animation is performed additively since iOS 8), I investigated how to fix the discontinuity in momentum and found a concise and spot-on summary on this topic:

TL;DR: The currently running animation isn’t removed when adding another animation for the same property — instead, multiple animations can contribute to the animated value simultaneously. This has minimal impact on performance and can greatly improve the feel of an app — as it did for us in all of the Android apps we develop at wirecube.

The API

While Google has just announced a new physics-based animation API that can be used to create a similar effect, their new API requires significant code changes and is cumbersome and unintuitive to use in most situations.

In contrast, let’s look at the code of the previous example:

AdditiveAnimator.animate(view).setDuration(1000)

.x(touch.getX())

.y(touch.getY())

.start();

That’s it. If this seems familiar, it’s because I deliberately stuck close to the ViewPropertyAnimator API to make conversion as simple as possible.

Animations are supported out of the box for a lot of attributes:

Everything that ViewPropertyAnimator supports ( x , y , z , translationX , translationY , translationZ , rotation , alpha etc).

supports ( , , , , , , , etc). Margins, padding, size, elevation and scroll position of views with appropriate LayoutProperties.

Background color of views with a ColorDrawable background.

background. Delta values for (almost) everything (the *By() methods of ViewPropertyAnimator ).

methods of ). Moving a view along a path (optionally, while rotating tangentially).

A more complex example

Here’s a fairly complex animation involving multiple views, hardware layers and delays:

It looks much better in 60fps (download video here).

Here’s the code it takes to create this animation:

AdditiveAnimator anim = new AdditiveAnimator().withLayer();

for(View v : views) {

anim = anim.target(v).x(x).y(y).rotation(r).thenWithDelay(50);

}

anim.start();

There’s a lot going on here, so let’s break it down step by step:

withLayer() enables hardware animations for all views you subsequently add to the animation. All views in this sample use alpha < 1 to show that performance isn’t affected. Even with hundreds of animations running at the same time, the animation runs smoothly thanks to withLayer() and the highly optimised core of AdditiveAnimator. In the example above, there are between 800 and 1200 animations running at all times (which is definitely overkill for most applications).

target(View v) changes the current animation target to the given view. There’s no need to use AnimatorSet when animating multiple views!

x(int x) , y(int y) , rotation(float degrees) are the methods that create animations for the current target, just like they do for ViewPropertyAnimator .