package com.marshalchen.common.uimodule.easyandroidanimations; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; /** * This animation causes the view to bounce by translating up and down for a * customizable number of times before returning to its original position. * * @author SiYao * */ public class BounceAnimation extends Animation { float bounceDistance; int numOfBounces, bounceCount = 0; TimeInterpolator interpolator; long duration; AnimationListener listener; /** * This animation causes the view to bounce by translating up and down for a * customizable number of times before returning to its original position. * * @param view * The view to be animated. */ public BounceAnimation(View view) { this.view = view; bounceDistance = 20; numOfBounces = 2; interpolator = new AccelerateDecelerateInterpolator(); duration = DURATION_LONG; listener = null; } @Override public void animate() { long singleBounceDuration = duration / numOfBounces / 4; if (singleBounceDuration == 0) singleBounceDuration = 1; final AnimatorSet bounceAnim = new AnimatorSet(); bounceAnim.playSequentially(ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, bounceDistance), ObjectAnimator.ofFloat( view, View.TRANSLATION_Y, -bounceDistance), ObjectAnimator .ofFloat(view, View.TRANSLATION_Y, bounceDistance), ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, 0)); bounceAnim.setInterpolator(interpolator); bounceAnim.setDuration(singleBounceDuration); ViewGroup parentView = (ViewGroup) view.getParent(), rootView = (ViewGroup) view .getRootView(); while (!parentView.equals(rootView)) { parentView.setClipChildren(false); parentView = (ViewGroup) parentView.getParent(); } rootView.setClipChildren(false); bounceAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { bounceCount++; if (bounceCount == numOfBounces) { if (getListener() != null) { getListener().onAnimationEnd(BounceAnimation.this); } } else { bounceAnim.start(); } } }); bounceAnim.start(); } /** * @return The maximum bounce distance. */ public float getBounceDistance() { return bounceDistance; } /** * @param bounceDistance * The maximum bounce distance to set. * @return This object, allowing calls to methods in this class to be * chained. */ public BounceAnimation setBounceDistance(float bounceDistance) { this.bounceDistance = bounceDistance; return this; } /** * @return The number of bounces. */ public int getNumOfBounces() { return numOfBounces; } /** * @param numOfBounces * The number of bounces to set. * @return This object, allowing calls to methods in this class to be * chained. */ public BounceAnimation setNumOfBounces(int numOfBounces) { this.numOfBounces = numOfBounces; return this; } /** * @return The interpolator of the entire animation. */ public TimeInterpolator getInterpolator() { return interpolator; } /** * @param interpolator * The interpolator of the entire animation to set. */ public BounceAnimation setInterpolator(TimeInterpolator interpolator) { this.interpolator = interpolator; return this; } /** * @return The duration of the entire animation. */ public long getDuration() { return duration; } /** * @param duration * The duration of the entire animation to set. * @return This object, allowing calls to methods in this class to be * chained. */ public BounceAnimation setDuration(long duration) { this.duration = duration; return this; } /** * @return The listener for the end of the animation. */ public AnimationListener getListener() { return listener; } /** * @param listener * The listener to set for the end of the animation. * @return This object, allowing calls to methods in this class to be * chained. */ public BounceAnimation setListener(AnimationListener listener) { this.listener = listener; return this; } }