package com.xdroid.animation.anim;
import com.xdroid.animation.base.AnimationBase;
import com.xdroid.animation.interfaces.Duration;
import com.xdroid.animation.interfaces.Orientation;
import com.xdroid.animation.utils.ViewHelper;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
/**
* Shake animation,This animation causes the view to shake from left to right
* for a customizable number of times before returning to its original position.
*
* @author Robin
* @since 2015-07-31 13:59:53
*
*/
public class ShakeAnimation extends AnimationBase<ShakeAnimation>{
float shakeDistance;
int numOfShakes, shakeCount = 0;
private int orientation = Orientation.HORIZONTAL;
/*
* ==================================================================
* Constructor
* ==================================================================
*/
public ShakeAnimation(View targetView) {
this.targetView = targetView;
shakeDistance = 20;
numOfShakes = 2;
interpolator = new AccelerateDecelerateInterpolator();
duration = Duration.DURATION_LONG;
listener = null;
}
/*
* ==================================================================
* Override CombinableMethod
* ==================================================================
*/
@Override
public void animate() {
createAnimatorSet().start();
}
@Override
public AnimatorSet createAnimatorSet() {
ViewHelper.setClipChildren(targetView, false);
long singleShakeDuration = duration / numOfShakes / 2;
if (singleShakeDuration == 0)
singleShakeDuration = 1;
final AnimatorSet shakeAnim = new AnimatorSet();
switch (orientation) {
case Orientation.HORIZONTAL:
shakeAnim.playSequentially(ObjectAnimator.ofFloat(targetView, View.TRANSLATION_X, shakeDistance),
ObjectAnimator.ofFloat(targetView, View.TRANSLATION_X, -shakeDistance),
// ObjectAnimator.ofFloat(targetView, View.TRANSLATION_X, shakeDistance),
ObjectAnimator.ofFloat(targetView, View.TRANSLATION_X, 0));
break;
case Orientation.VERTICAL:
shakeAnim.playSequentially(ObjectAnimator.ofFloat(targetView,View.TRANSLATION_Y, shakeDistance),
ObjectAnimator.ofFloat(targetView, View.TRANSLATION_Y, -shakeDistance),
// ObjectAnimator.ofFloat(targetView, View.TRANSLATION_Y, shakeDistance),
ObjectAnimator.ofFloat(targetView, View.TRANSLATION_Y, 0));
break;
}
shakeAnim.setInterpolator(interpolator);
shakeAnim.setDuration(singleShakeDuration);
shakeAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
if (listener != null) {
listener.onAnimationStart(animation);
}
}
@Override
public void onAnimationEnd(Animator animation) {
shakeCount++;
if (shakeCount == numOfShakes) {
if (listener != null) {
listener.onAnimationEnd(animation);
}
} else {
shakeAnim.start();
}
}
@Override
public void onAnimationCancel(Animator animation) {
if (listener != null) {
listener.onAnimationCancel(animation);
}
}
@Override
public void onAnimationRepeat(Animator animation) {
if (listener != null) {
listener.onAnimationRepeat(animation);
}
}
});
return shakeAnim;
}
/*
* ==================================================================
* Getter And Setter
* ==================================================================
*/
public int getOrientation() {
return orientation;
}
public ShakeAnimation setOrientation(int orientation) {
this.orientation = orientation;
return this;
}
/**
* @return The maximum shake distance.
*/
public float getShakeDistance() {
return shakeDistance;
}
/**
* @param shakeDistance
* The maximum shake distance to set.
* @return ShakeAnimation
*/
public ShakeAnimation setShakeDistance(float shakeDistance) {
this.shakeDistance = shakeDistance;
return this;
}
/**
* @return The number of shakes.
*/
public int getNumOfShakes() {
return numOfShakes;
}
/**
* @param numOfShakes
* The number of shakes to set.
* @return ShakeAnimation
*/
public ShakeAnimation setNumOfShakes(int numOfShakes) {
this.numOfShakes = numOfShakes;
return this;
}
}