I recently completed a financial charting tool with several user controlled variables, such as interest rate, term, loan amount. One client request was on the reset to default values there should be an animation while incrementing/decrementing rather than the value jumping instantly. I decided a non-linear animation algorithm would give the best visual result by adjusting the values quickly before decelerating as the target value approached. The graph below shows the required deceleration over time.

You may recognize this as a common interpolation pattern used in Android for animating movement of views. With this in mind I decided the most flexible design was to utilize the built-in Android Interpolator classes to control the rate of increment/decrement while using ValueAnimator. I have packaged the end result into an easy to use class, AnimateCounter.

## AnimateCounter

AnimateCounter is a simple to use class to animate a numerical count on any TextView derived object. Full source code is available here.

The animation below shows an example of AnimateCounter being used to animate four TextViews from 0 to 100. Notice how the rate of numerical change for each view is influenced by the use of the different Interpolators.

### Features of AnimateCounter

- Ascending or descending value animation
- Supports standard Android Interpolator classes
- Supports custom Interpolator classes
- Decimal and floating point number support
- Numerical precision support
- Optional callback on completion

### AnimateCounter Usage

An AnimateCounter object is constructed using the builder design pattern. At a minimum a TextView is required for construction, then use the builder functions to optionally set initial and final values, precision, total duration and the interpolator required for animation. If no interpolator is provided the ValueAnimator default, AccelerateDecelerateInterpolator, is used.

**Example 1: Count from 0 to 100 in two seconds using the default AccelerateDecelerateInterpolator interpolation.**

AnimateCounter animateCounter = new AnimateCounter.Builder(textView) .setCount(0, 100) .setDuration(2000) .build(); animateCounter.execute();

**Example 2: Count from 0.00 to 1.00 (floating point number with 2 decimal places) in 10 seconds using LinearInterpolator.**

AnimateCounter animateCounter = new AnimateCounter.Builder(textView) .setCount(0f, 1f, 2) .setDuration(10000) .setInterpolator(new LinearInterpolator()) .build(); animateCounter.execute();

**Example 3: Perform an action after counting from 10 to 0 using the OvershootInterpolator.**

AnimateCounter animateCounter = new AnimateCounter.Builder(textView) .setCount(10, 0) .setDuration(2000) .setInterpolator(new OvershootInterpolator()) .build(); animateCounter.setAnimateCounterListener(new AnimateCounter.AnimateCounterListener() { @Override public void onAnimateCounterEnd() { // Add action here! } }); animateCounter.execute();

## Built-in Interpolators

Here are some of the Interpolators that you may like to use to animate the numerical change. These are all provided as part of the Android SDK:

- AccelerateDecelerateInterpolator: Slow to start and end but accelerates through the middle.
- AccelerateInterpolator: Starts slow before accelerating.
- AnticipateInterpolator: Initially backward before flinging forward.
- AnticipateOvershootInterpolator: Initially backward before flinging forward and overshooting above the final value before returning to the final value.
- BounceInterpolator: Rate of change bounces at the final value.
- DecelerateInterpolator: Starts quickly before decelerating.
- LinearInterpolator: Constant rate of change.
- OvershootInterpolator: Flings forward and overshoots the last value before returning.

## Roll your own: Custom Interpolators

If none of the built in Interpolators fit your needs it is simple to create your own. The following class shows how to create an acceleration deceleration interpolation result. You could replace the mathematical formula in this class as required to produce your desired result.

import android.view.animation.Interpolator; public class CustomAccelerateDecelerateInterpolator implements Interpolator { /** * Maps a value representing the elapsed fraction of an animation to a value that represents * the interpolated fraction. This interpolated value is then multiplied by the change in value * of an animation to derive the animated value at the current elapsed animation time. * * @param input A value between 0 and 1.0 indicating our current point in the animation * where 0 represents the start and 1.0 represents the end * * @return The interpolation value. This value can be more than 1.0 for interpolators * which overshoot their targets, or less than 0 for interpolators that undershoot their targets. */ public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; } }

Graphing tools can be used to visualize the interpolation algorithms and are the best place to start if you want to build our own custom interpolator. Here is an example.

**Step 1. Find a mathematical equation for interpolation.** The following equation shows a formula used in the Android accelerate/decelerate interpolator, where time is represented by t.

**Step 2. Graph your equation.** Visit graphsketch.com or any graphing site and enter in the formula. When using graphsketch.com it is required in this format:

cos((x+1)pi)/2)+0.5

The generated graph should confirm if the output from the formula is going to meet your needs. Using the above example the following graph is produced. Note the acceleration during the first half of the duration and the deceleration during the final half.

**Step 3. Convert into Java.** To use in your custom interpolator you need to convert your equation into Java code, for example:

cos((x+1)pi)/2)+0.5 (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;

## Source Code

Source for AnimateCounter available on GitHub

## Attribution

“Count von Count kneeling” by Source. Licensed under Fair use via Wikipedia – https://en.wikipedia.org/wiki/File:Count_von_Count_kneeling.png#/media/File:Count_von_Count_kneeling.png