Dynamic Lottie Animations on Android

Kohleen Fortuno
Healint-Engineering&data
5 min readFeb 18, 2021

Using Lottie animations is an inexpensive way to add pizzazz into your mobile app. It’s quick to setup and it provides several animation possibilities. Since there are enough helpful tutorials out there about basic Lottie usage, I want to focus on sharing with you how we implemented special effects in our app with only one Lottie animation file.

Found a pretty Lottie animation you want to use but it doesn’t exactly suit your Android app? Stick until the end to see the different tweaks you can do!

The motivation

A little backstory: one of the things our app Migraine Buddy does is provide weather forecast information and it has proven to be helpful for our users. We added a section in our homepage that presents upcoming changes in atmospheric pressure and we wanted it to have a pleasant loading and appearing experience.

Pressure variation forecast feature in Migraine Buddy

Each circle, representing a day of the week, uses the same Lottie animation file (below) and as you can see, there are different states one circle can be.

Lottie animation

Basically, there were three main things we needed to achieve:

  1. Make the loading spinner play continuously until the actual data is available
  2. Show the question mark for unknown state
  3. The final colour should depend on the intensity of pressure variation that day: green for low, yellow for moderate, and red for high

Let’s look at how we did it!

Controlling frame playback

The first two items were quite simple: all we needed was the frame number/s of what we wanted to show.

This is the code for displaying only the question mark while the user hasn’t tapped on the button to update yet:

private void showFrame(int frame) {
if (animation.isAnimating()) {
animation.pauseAnimation();
}
animation.setMinAndMaxFrame(FIRST_FRAME, LAST_FRAME);
animation.setFrame(frame);
}

For playing the loading frames on repeat, we used this:

private void loopFrames(int min, int max) {
animation.setSpeed(1f);
animation.setMinAndMaxFrame(min, max);
animation.setRepeatCount(LottieDrawable.INFINITE);
animation.playAnimation();
}

If somehow we cannot fetch the pressure variation data, we have to smoothly animate back to the question mark from the loading state by playing the file in reverse:

private void animateToUnknownState(int delay) {
animation.setSpeed(-1f);
animation.setMinAndMaxFrame(0, 9);
animation.setRepeatCount(0);
animation.playAnimation();
}

NOTE: If you are manipulating playback here and there, make sure that the frames you want to be showing are always within the animation’s current minAndMax frames and that your speed is correct.

Modifying KeyPaths

For the third goal, we needed to explore KeyPaths. If you’re not yet familiar, KeyPaths are the layers that make up a Lottie animation — think shapes, strokes, fills, groupings. Fortunately, Lottie allows programatically modifying KeyPath properties such as colour, size and opacity so we can alter the look of specific parts of the animation.

In our case, we want to change the colours of the solid circle and its semi-transparent ‘shadow’ so we look for which layers or KeyPaths they are.

Lottie animation snippet
The specific layers of the animation we want to change

We use the resolveKeyPath() method to list the available layers in the animation hierarchy:

With some trial and error, we identified these layers as our targets:

keys=[round, shape_2 2, group 1, fill 1]
keys=[round, shape_2 , group 1, fill 1]

Now that we know which KeyPaths to modify, we create KeyPath objects that we will pass to the Lottie SDK. In Android, we select KeyPaths as arrays of strings. So to target our 2 layers, we used new KeyPath("**", "shape_2 ", "group 1", "fill 1")and new KeyPath("**", "shape_2 2", "group 1", "fill 1"). What do these strings mean?

The Globstar

The first string, "**", is what we call a “globstar”. It matches 0 or more items in the hierarchy. So if we wanted to target all these layers for example…

keys=[round, shape_2 2, group 1, fill 1]
keys=[round, shape_2 , group 1, fill 1]
keys=[rectangle, shape_3, group 1, fill 1]
keys=[rectangle, shape_4, group 1, fill 1]

… we can use new KeyPath("**", "group 1", "fill 1"). This will get all KeyPaths that end in "group 1" and "fill 1".

The Wildcard

One thing I learned is that there is a small difference in the Android and iOS Lottie SDKs in the use of wildcards. Wildcards, represented by a single asterisk "*", are similar to globstars except they only match 1 item in the hierarchy. This is the case for both platforms. In iOS however, a wildcard can also be used to match a part of the string. For example, our iOS app only uses "shape_2 *" while in Android we needed 2 KeyPaths, one with "shape_2 " and one with "shape_2 2".

The Value Callback

Modifying the KeyPath means adding a value callback to the animation, passing the KeyPath, the property we want to edit, and the value we want to apply as parameters.

private void changeColor(int color) {
animation.addValueCallback(new KeyPath("**", "shape_2 ", "group 1", "fill 1"), LottieProperty.COLOR_FILTER,
lottieFrameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
animation.addValueCallback(new KeyPath("**", "shape_2 2", "group 1", "fill 1"), LottieProperty.COLOR_FILTER,
lottieFrameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
}

The third parameter is the LottieValueCallback which as per Lottie documentation “allows you to set a callback on a resolved KeyPath to modify its animation values at runtime”. It gets called every time the animation is rendered. In our example, what we’re doing in the callback is applying a colour overlay on the frames with the help of PorterDuffColorFilter.

As I mentioned earlier, there are many properties that can be modified such as scale, position, fill colour, fill opacity, stroke colour, stroke opacity, stroke width, and so on. The list of values that can be modified are listed in the Lottie documentation.

The Final Result

That’s it! I hope you were able to see how Lottie opens a world of promises for elegant animations with only 1 file and a few lines of code. Figuring out your target KeyPaths and the value callbacks you want to use could be challenging at first, but it’s also what can be fun to play around with!

Thank you for reading and enjoy animating!

--

--