How to animate on Android

Irina Galata
ProAndroidDev
Published in
8 min readJul 22, 2017

--

Previously I have described how to create animations for both native Android and React Native applications using OpenGL. This time I’d like to tell about different tools which could be useful for Android animations of any difficulty and their pros and cons. This article is not a tutorial or something similar; it is a small collection of my thoughts and recommendations about animating in Android.

Tools I don’t use

However, the first thing I’d like to start from is tools, which I don’t use, and why. Some of them I used in my opensource animations, but I don’t want to use them further. Of course, it’s just my subjective opinion, and it’s not a call for refactoring of your recent animation :)

ObjectAnimator

ObjectAnimator.ofFloat(image, "x", 0f, 300f).apply {
duration = 1000
start()
}

The code snippet above shows usage of the ObjectAnimator. In this case, the x property of my image changes through reflection, which is not a good idea while animating. The reflection mechanism is great, but it’s a bit overhead for simple animations. Of course, we can solve that by using the Property instead of hardcoding the property name.

ObjectAnimator.ofFloat(image, View.X, 0f, 300f).apply {
duration = 1000
start()
}

Now the property value changes using appropriate setter directly without reflection. So right now we can see the first small disadvantage of the ObjectAnimator — you need to create Property for every custom property you want to modify to avoid using reflection.

The other issue is that you need a new ObjectAnimator for every view you want to modify since it doesn’t support simultaneous changes of several objects.

Anyway, it worth to say that ObjectAnimator is widely used in AnimatedVectorDrawable to animate SVG due to its ability to animate a property of any type. In my opinion, in any other case, there are better solutions for animations.

Animation and its subclasses

image.startAnimation(TranslateAnimation(0f, 300f, 0f, 0f).apply { 
duration = 1000
})

Animation is the abstract parent class of TranslateAnimation, RotateAnimation, AlphaAnimation, ScaleAnimation and AnimationSet.

They could be useful to animate single view property, in any other circumstances Animation subclasses require to setup several instances to play AnimationSet just like ObjectAnimator does. And another big disadvantage is that you can animate only basic properties like rotation, scale, alpha and position (e.g., not a background color) and these tools are restricted to View's subclasses only. One more issue you face if you use Animation is that it animates a View's pixel only, not a View itself, e.g., you apply TransitionAnimation to your object, but it stays clickable in the previous location, if not to specify different behavior.

For now, the only reasonable usage of the Animation is the transitions between activities or fragments.

ViewPropertyAnimator

ViewPropertyAnimator is created to substitute the ObjectAnimator, and it’s adapted to simultaneous modifications due to optimization of the invalidate() method calls, which doubtlessly is good news. It’s a great tool, to animate several properties of a view in parallel.

image.animate().apply { 
duration = 1000
x(300f)
y(150f)
alpha(0.5f)
start()
}

It looks much better, isn’t it? But usually animation requires to animate several views at the same time and not only views but other objects, so it’s still not good enough.

Tools I use

While reading the previous part, you may think that I’m too exacting to these instruments. But in most cases, they could be easily replaced by ValueAnimator.

ValueAnimator

ValueAnimator.ofFloat(0f, 300f).apply {
duration = 1000
addUpdateListener {
image.x = it.animatedValue as Float
anotherImage.y = interpolate(100f, 500f, it.animatedFraction)
}
start()
}
fun interpolate(a: Float, b: Float, f: Float) = a + f * (b - a)

So, ValueAnimator allows us to animate any number of objects of any type at the same time using one instance of it. And you can use not only the animated value but the fraction to be able to interpolate between other two values without creating a new instance of ValueAnimator. Great!

Animation implemented using ValueAnimator — UX concept by Marcus J Potter

Both parts (record button and countdown) of the animation above are implemented using ValueAnimator.

Take a look at another animation created with ValueAnimator for Yalantis and its source code:

Animation implemented using ValueAnimator

When to use:
1. For animations of simple and middle difficulty, which transformations are possible to represent as linear or any other mathematical function.

Physics-based animations

Recently a new tool for animations on Android was introduced to developers — Physics-based Animations. A great thing, which helps to make objects move physically plausible without overhead like a physical engine in simple animations. It consists of two main classes — SpringAnimation and FlingAnimation.

Using SpringAnimation, you can make your View move like a spring with specified damping, stiffness and final position:

SpringAnimation(image, DynamicAnimation.TRANSLATION_Y, 700f).apply {
spring.stiffness = 40f
spring.dampingRatio = 0.2f
}.start()

FlingAnimation helps to create smoother and more feasible fling movement of the View. Its start velocity and friction are possible to customize.

FlingAnimation(image, DynamicAnimation.TRANSLATION_X).apply {
startVelocity = 100 // pixels per second
friction = 0.5f
}.start()

When to use:
1. For animations, which require objects move in a physically realistic way without complex interaction with other objects (e.g., collisions)

Canvas

As I’ve mentioned earlier, sometimes, it’s not enough to animate View's subclasses only. To draw all the stuff by yourself, you need to use Canvas, which is accessible in onDraw() method of any View. It allows drawing anything from simple circle to bezier curves or text.

path.apply {
moveTo(0f, 0f)
lineTo(width.toFloat(), 0f)
lineTo(width.toFloat(), height.toFloat())
lineTo(0f, height.toFloat())
quadTo(0f, height / 2f, 150f, 0f)
}
canvas?.drawPath(path, paint)

Path and Paint are helper classes of Canvas, which contains geometric paths and style data respectively.

Check out my animation created using features of Canvas and ValueAnimator:

Animation implemented using Canvas and ValueAnimator

Canvas is a great tool and it works quite fast, but for small areas. If you try to use it to draw the whole screen, you’ll notice that every frame is drawn for more than 16 ms, which causes animation glitches.

When to use:
1. For more complex animations, which are not possible/easy to represent as a combination of views.

OpenGL

OpenGL is a heavy artillery in Android animations. It’ll work fine when Canvas can’t cope with significant areas of drawing.

The usage of OpenGL is becoming wider every year — games, difficult 2D and 3D animations, photo and video effects, augmented reality and virtual reality applications. Don’t lose your time, start learning OpenGL today!

To find out about basics in OpenGL and to check out the example animation review my article:

Also, I highly recommend to read this book to get more acquainted with OpenGL:

This tool is convenient to check your shaders or share them with your friends or colleagues:

When to use:
1. For huge and continuously rendering animations
2. For 3D animations
3. For animations with complex transformations

Physics engines

To create difficult physically plausible animations with interactions between objects, you’ll certainly need to use a physics engine.

I chose Box2D for myself. It’s a C++ library, which has plenty of ports in another programming languages, and if you’re acquainted with one of them, you can work with any one. It’s very lightweight and doesn’t require you to make any architectural changes (as opposite to LibGDX, which is quite good for games though). Also, its community is quite large, and you can find an answer for any question independently from the platform and programming language.

You can use the original native library or its Java port called JBox2D on Android.

Animation implemented using OpenGL and JBox2D

When to use:
1. For simple 2D games
2. For advanced animations, which require complex interactions between objects

Interpolators

One of the main things you need to learn to create animations is interpolators. They are used in animations on every platform and in any programming language. Interpolator describes how your animation value will be changed during the timeline. You can find some ready interpolators in Android SDK like AccelerateInterpolator, DecelerateInterpolator, AccelerateDecelerateInterpolator, OvershootInterpolator, etc. To learn about the difference between them check out this article:

To dive a bit deeper read this article:

To create one on Android, you need to implement Interpolator interface.

class CustomInterpolator: Interpolator {
override fun getInterpolation(input: Float): Float {
// todo return your function value
}
}

After that you can use it with ValueAnimator:

ValueAnimator.ofFloat(0f, 300f).apply {
duration = 1000
interpolator = CustomInterpolator()
addUpdateListener {
image.x = it.animatedValue as Float
anotherImage.y = interpolate(100f, 500f, it.animatedFraction)
}
start()
}
fun interpolate(a: Float, b: Float, f: Float) = a + f * (b - a)

I can recommend you a quite useful tool to help you to create your interpolator, where you can see an animated example of any interpolator:

Also, you can use PathInterpolator to generate custom interpolator at the runtime by the control points of the needed bezier curve:

interpolator = PathInterpolator(0f, 0.3f, 0.1f, 0.2f)

This could replace the code above for pre-lollipop:

interpolator = PathInterpolatorCompat.create(0f, 0.3f, 0.1f, 0.2f)

As a conclusion, I’d like to say that there is no one universal tool or advice on how to create animations on Android, the solution depends on the many circumstances a lot — e.g., the difficulty of a component, time resources availability, etc. Every time weigh the advantages and disadvantages before making the choice of instruments.

It seems like that’s all for now. Thank you for reading my article and have fun with animations! :)

--

--