package net.qiujuer.tips.common.drawable;
import android.os.SystemClock;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
public abstract class TouchAnimateDrawable extends TouchDrawable {
protected static final long FRAME_DURATION = 16;
// Base Values
protected static final Interpolator DECELERATE_INTERPOLATOR = new DecelerateInterpolator(2.8f);
protected static final Interpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
// Time
protected static final int IN_ANIM_DURATION = 280;
protected static final int OUT_ANIM_DURATION = 160;
private boolean isAnimatingIn = false;
private Interpolator mInterpolator = DECELERATE_INTERPOLATOR;
private long mStartTime;
private int mDuration = IN_ANIM_DURATION;
@Override
protected void onTouchDown(float x, float y) {
// Cancel and Start new animation
cancelAnim();
startInAnim();
}
@Override
protected void onTouchReleased(float x, float y) {
if (!isAnimatingIn) {
startOutAnim();
}
}
@Override
protected void onTouchMove(float x, float y) {
}
private void startInAnim() {
isAnimatingIn = true;
isRunning = true;
mDuration = IN_ANIM_DURATION;
mInterpolator = DECELERATE_INTERPOLATOR;
// Start animation
mStartTime = SystemClock.uptimeMillis();
scheduleSelf(mInAnim, mStartTime);
}
private void startOutAnim() {
mDuration = OUT_ANIM_DURATION;
mInterpolator = ACCELERATE_INTERPOLATOR;
// Start animation
mStartTime = SystemClock.uptimeMillis();
scheduleSelf(mOutAnim, mStartTime);
}
private void cancelAnim() {
unscheduleSelf(mInAnim);
unscheduleSelf(mOutAnim);
isRunning = false;
}
private final Runnable mInAnim = new Runnable() {
@Override
public void run() {
long currentTime = SystemClock.uptimeMillis();
long diff = currentTime - mStartTime;
if (diff <= mDuration) {
float interpolation = mInterpolator.getInterpolation((float) diff / (float) mDuration);
// Notify
onInAnimateUpdate(interpolation);
invalidateSelf();
// Next
scheduleSelf(this, currentTime + FRAME_DURATION);
} else {
unscheduleSelf(this);
// Notify
onInAnimateUpdate(1f);
invalidateSelf();
// End
isAnimatingIn = false;
// Call end
onInAnimateEnd();
// Is un touch auto startOutAnim()
if (isTouchReleased) startOutAnim();
}
}
};
private final Runnable mOutAnim = new Runnable() {
@Override
public void run() {
long currentTime = SystemClock.uptimeMillis();
long diff = currentTime - mStartTime;
if (diff <= mDuration) {
float interpolation = mInterpolator.getInterpolation((float) diff / (float) mDuration);
// Notify
onOutAnimateUpdate(interpolation);
invalidateSelf();
// Next
scheduleSelf(this, currentTime + FRAME_DURATION);
} else {
unscheduleSelf(this);
// Notify
onOutAnimateUpdate(1f);
invalidateSelf();
// End
isRunning = false;
// Call end
onOutAnimateEnd();
// Click
performClick();
}
}
};
protected abstract void onInAnimateUpdate(float factor);
protected abstract void onOutAnimateUpdate(float factor);
protected abstract void onInAnimateEnd();
protected abstract void onOutAnimateEnd();
}