Open In App

Interpolator in Android with Example

An interpolator is a function (in the mathematical sense) that outputs values “interpolated” between a range of values that are given to it as input. Interpolation is simply a method to generate new data points between two fixed data points. The exact values of these generated data points are determined by the kind of interpolation is performed. For example, in linear interpolation, all the generated values are evenly distributed between the fixed points. While an understanding of interpolation is helpful, it isn’t necessary to get started animating your views in your apps. In fact, the animation perspective of interpolation might prove helpful in understanding it! So, let’s get started. In this example, we’ll create a simple app with a list of buttons. Each of these buttons is for a specific type of interpolated animation which kicks off when you press it. The animation is a simple horizontal translation that moves the button to the right.

The Interpolator Interface

In the Android development framework, Interpolator is defined as an interface. This allows methods to accept an interpolator that can bring its own configuration and not tie developers to a specific implementation. As of this writing, there are 11 indirect subclasses of the Interpolator interface. They are:



Creating the App

To better understand the above-mentioned classes and see them in action, it’s highly recommended you follow along with an actual project and run the app as you build it.

Step 1: Working with the activity_main.xml file



Go to the activity_main.xml file and refer to the following code. Below is the code for the activity_main.xml file.




<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="16dp">
  
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Interpolators"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/linear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Linear"
            android:textColor="#FFF" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/accelerate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Accelerate"
            android:textColor="#FFF" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/decelerate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Decelerate"
            android:textColor="#FFF" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/bounce"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Bounce"
            android:textColor="#FFF" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/overshoot"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Overshoot"
            android:textColor="#FFF" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/anticipate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Anticipate"
            android:textColor="#FFF" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/cycle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Cycle"
            android:textColor="#FFF" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/accelerateDecelerate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Accelerate Decelerate"
            android:textColor="#FFF" />
  
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/anticipateOvershoot"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Anticipate Overshoot"
            android:textColor="#FFF" />
  
    </LinearLayout>
</ScrollView>

Step 2: Working with the MainActivity.java file

Setup ObjectAnimator Object: For this example, we’ll use a single ObjectAnimator to animate the different buttons. We’ll also use a fixed duration of 2 seconds for the animations to play out, this gives us ample time to observe the animation behaviors. You can have this set up with 2 lines of code as below.




// 2-second animation duration
final private static int ANIMATION_DURATION = 2000;
private ObjectAnimator animator;

Setup Animations on Button Click: Now that we have the pre-requisites setup, we can finally get to configuring the buttons to trigger their respective animations. For each button, you can configure the specific property to animate, its duration, and the interpolation, among other things. The basic three-step configuration is performed as shown in the code snippet below:




// Linear
binding.linear.setOnClickListener(clickedView -> {
    animator = ObjectAnimator.ofFloat(binding.linear,"translationX", 200f);
    animator.setInterpolator(new LinearInterpolator());
    animator.setDuration(ANIMATION_DURATION);
    animator.start();
});

Below is the complete code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.




import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.CycleInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import androidx.appcompat.app.AppCompatActivity;
import com.example.doobar.databinding.ActivityMainBinding;
  
public class MainActivity extends AppCompatActivity {
    
    // 2-second animation duration
    final private static int ANIMATION_DURATION = 2000
  
    private ActivityMainBinding binding;
    private ObjectAnimator animator;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);
  
        // setup animation buttons
  
        // Linear
        binding.linear.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.linear, "translationX", 200f);
            animator.setInterpolator(new LinearInterpolator());
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
  
        // Accelerate
        binding.accelerate.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.accelerate, "translationX", 200f);
            animator.setInterpolator(new AccelerateInterpolator());
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
  
        // Decelerate
        binding.decelerate.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.decelerate, "translationX", 200f);
            animator.setInterpolator(new DecelerateInterpolator());
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
  
        // Bounce
        binding.bounce.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.bounce, "translationX", 200f);
            animator.setInterpolator(new BounceInterpolator());
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
  
        // Overshoot
        binding.overshoot.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.overshoot, "translationX", 200f);
            animator.setInterpolator(new OvershootInterpolator());
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
  
        // Anticipate
        binding.anticipate.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.anticipate, "translationX", 200f);
            animator.setInterpolator(new AnticipateInterpolator());
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
  
        // Cycle
        binding.cycle.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.cycle, "translationX", 200f);
            animator.setInterpolator(new CycleInterpolator(2));
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
  
        // Accelerate Decelerate
        binding.accelerateDecelerate.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.accelerateDecelerate, "translationX", 200f);
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
  
        // Anticipate Overshoot
        binding.anticipateOvershoot.setOnClickListener(clickedView -> {
            animator = ObjectAnimator.ofFloat(binding.anticipateOvershoot, "translationX", 200f);
            animator.setInterpolator(new AnticipateOvershootInterpolator());
            animator.setDuration(ANIMATION_DURATION);
            animator.start();
        });
    }
}

Output: Run the App

Having built the buttons and having set them up to trigger animations when pressed, you’re all set to fire up the app and see your animations come to life. And you’re done! That’s how you use interpolators in your animations to spice them up and not make them look monotonic.

You can view the entire application here: https://github.com/krishnakeshan/android-interpolators.


Article Tags :