January 12, 2014

For those beginning to use Animations in Android.

ViewPropertyAnimator and using interpolators…

For those beginning to use Animations in Android.

Background info

With UI/UX taking the center stage in Android, the dev team introduced the ViewPropertyAnimator in v3.0(HoneyComb) to simplify how we animate views. Compared to the original Animation API and ObjectAnimators, a ViewPropertyAnimator is more efficient, especially when animating 2 or more properties, and it’s syntax is also a lot cleaner.

When we are using any animation API, we may want to use an Interpolator. There are many types of Interpolator and they are all responsible for one thing, skewing output of the animation to give an added effect. This effect could be, but are not limited to, an acceleration, deceleration, or even a bounce.

cos(​(x+​1)*​π)/​2+​0.5

An interpolator has an input value from 0 to 1. This value gets plugged into a formula and the result of the equation is the interpolated value.

The diagram to the left illustrates the the values output from the AccelerateDecelerate interpolator (default for ViewPropertyAnimator) . On-screen, the animation will start slow, speed up and then slow down before coming to rest.


The Situation

So, lets say we have a sweet little form that has a bunch of EditTexts. Each EditText does some fancy text validation and the result is one of two possible animations:

1.) Error — When moving to the next focusable view, the EditText should do a “shake” animation to indicate an invalid input. The shake would be a movement along the X-axis of 8 dips, back and forth

//The following code could be how we implement the animation.I //extended the duration as the default duration(300ms) would be //a bit too fast. 

editText.animate().translationX(8dp).setInterpolator(new CycleInterpolator(2)).setDuration(450);

2.) Valid — Move the EditText outside of its parent, so thats its not visible, and animate a new view in to take its place.

//Lets assume that editText is starting off at position  0 and //otherView is starting off at position -mParentWidth. For the z-//order, otherView is on-top of editText 

editText.animate().translationX(mParentWidth); otherView.animate().translationX(0);

The problem we will run into.

When we put input some invalid text, the view will do a jiggle. Now, lets say we immediately fix our error. You would think the “valid-state” animation would trigger… it will, but not as we would expect. Because we didn't set an interpolator on the EditText in the valid-state, it will reuse the CycleInterpolator that was set in the error-state. Our output animation will be the EditText doing a massive shake (because we are moving a distance of mParentWidth) and otherView will then animate and rest on top of it. That ain’t right.


The Solution

We can’t let the view reuse its interpolator so setting the valid-state animation’s interpolator back to default would suffice.

What else? Since we’re only doing a simple translate, using ObjectAnimator for both our animations would work as well.