I will say one more time -- it's not another rebound tutorial nor is it any physics library or spring library, it's a tutorial on pure view animation. Okay, now that I have almost made myself clear, let's talk about springs.

As per Wikipedia,

 A spring is an elastic object used to store mechanical energy.

Hmm, mechanical energy seems fun but we can't really do the mechanical thing with software, instead we produce an illusion. We will do the same with our button, an illusion of tension and release to make it feel like a mechanical spring. We will use ViewPropertyAnimator on the button for getting the desired result.

We will assume a Button layout is already present for us, please create one if you don't have it already. We then reference the layout button object using findViewById(...) and apply ViewPropertyAnimator on it. But first, let's find out what a ViewPropertyAnimator is actually and how it helps get the illusion created.

As the name suggests, ViewPropertyAnimator animates the view in question based on its property (-ies). We can translate a view from one location to another, or change its location or scale it up or down using VPA. We have also got the freedom to set the duration of animation or how the animation should behave with interpolators. In our case we will simply be using scaleBy to scale our view's size up and down whenever a button click  event is triggered.

final Button button = (Button) findViewById(R.id.v);
final ViewPropertyAnimator animator = button.animate();
animator.setDuration(200);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
button.setEnabled(false);
animator.scaleXBy(-0.06f)
.scaleYBy(-0.06f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animator.scaleXBy(0.06f)
.scaleYBy(0.06f)
.setListener(null)
.withEndAction(new Runnable() {
@Override
public void run() {
button.setEnabled(true);
}
});
}
});
}
});

All android componets that extend View class have an animate() method that returns a ViewPropertyAnimator object for us to play with. We will declare an object of VPA with the animate method of our button (which is also a view) like this,

ViewPropertyAnimator animator = button.animate();

We will apply a fixed duration (in microseconds) of animation with setDuration(...). In this example, we won't be using any interpolators, but feel free to experiment with them to get different results.

Okay. Since we want to the animation to work only when the button is clicked, we will do all the animation inside button's onClick method, but first we need to disable button on every click to eliminate animation repeatition. We will re-enable the button when the animation ends.

After disabling button, we move to scale the button down with scaleXBy(...) and scaleYBy(...). We have chosen to scale it down by -0.06 times the original size on both axes. You can have any other scale factor if you like. Now that we have our button scaled down, we will need to get it back to its original size. We will listen to our first animation, and as soon as it ends we again scale up by the same factor.

Take a look at the example code above. You will notice that the second time, while scaling up, we have remove the listener by setting it to null. That's because we don't to go into an infinite loop of up scale. As mentioned earlier, when the scale up animation is done, we will release the button -- re-enable it. We will take the help of withEndAction(...) that is triggered on animation end. This method requires a runnable interface. The run method of runnable is invoked when the animation ends. Putting this inside the run block will re-enable our button,

button.setEnabled(true);

That's it. We have our spring animation ready for button. Run the project and see it in action. We used simple scale animation on button to get a spring like behaviour, however, there is a predefined class to do the same which follows the same procedure. Scale down and then up. We will discuss about SpringAnimation in some other post.