Skip to content

Instantly share code, notes, and snippets.

@JayNewstrom
Created November 11, 2014 21:58
Show Gist options
  • Save JayNewstrom/bd75d9e304d1259a3640 to your computer and use it in GitHub Desktop.
Save JayNewstrom/bd75d9e304d1259a3640 to your computer and use it in GitHub Desktop.
A helper class to allow animation based touch states.
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Transformation;
public final class TouchEffectAnimator {
private static final int EASE_ANIM_DURATION = 200;
private static final int MAX_RECT_ALPHA = 150;
private final View view;
private final int slop;
private int animInDuration = EASE_ANIM_DURATION;
private int animOutDuration = EASE_ANIM_DURATION;
private int rectAlpha = 0;
private Paint rectPaint = new Paint();
private Path rectPath = new Path();
private RectF viewRect;
private boolean touchReleased = true;
private boolean animatingFadeIn = false;
private Animation animationInProgress;
private boolean canceled;
private boolean hasPerformedFadeInAnimation;
private float downX;
private float downY;
public static TouchEffectAnimator setupListTouchEffectAnimator(View view) {
TouchEffectAnimator t = new TouchEffectAnimator(view);
t.setEffectColor(Color.LTGRAY);
t.setAnimInDuration(200);
t.setAnimOutDuration(500);
return t;
}
private final Animation.AnimationListener animationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
animatingFadeIn = true;
}
@Override
public void onAnimationEnd(Animation animation) {
animationInProgress = null;
if (canceled) {
canceled = false;
} else {
animatingFadeIn = false;
if (touchReleased) {
fadeOutEffect();
}
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
public TouchEffectAnimator(View view) {
this.view = view;
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
this.slop = vc.getScaledTouchSlop();
}
public void setAnimInDuration(int animInDuration) {
this.animInDuration = animInDuration;
}
public void setAnimOutDuration(int animOutDuration) {
this.animOutDuration = animOutDuration;
}
public void setEffectColor(int effectColor) {
rectPaint.setColor(effectColor);
rectPaint.setAlpha(rectAlpha);
}
public void onTouchEvent(final MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
canceled = true;
touchReleased = true;
hasPerformedFadeInAnimation = false;
if (animationInProgress != null) {
animationInProgress.cancel();
animationInProgress = null;
}
rectAlpha = 0;
view.invalidate();
animatingFadeIn = false;
}
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
touchReleased = true;
canceled = false;
if (!hasPerformedFadeInAnimation) {
fadeInEffect();
} else if (!animatingFadeIn) {
fadeOutEffect();
}
} else if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
canceled = false;
if (touchReleased) {
touchReleased = false;
downX = event.getX();
downY = event.getY();
view.postDelayed(new Runnable() {
@Override public void run() {
if (!canceled && !hasPerformedFadeInAnimation) {
fadeInEffect();
}
}
}, 100);
}
} else if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
if (!touchReleased && animationInProgress == null) {
if (Math.abs(downX - event.getX()) > slop || Math.abs(downY - event.getY()) > slop) {
canceled = true;
touchReleased = true;
}
}
}
}
public void onDraw(final Canvas canvas) {
if (rectPaint.getAlpha() != rectAlpha) {
rectPath.reset();
rectPaint.setAlpha(rectAlpha);
}
canvas.drawRoundRect(getViewRect(), 0, 0, rectPaint);
}
private RectF getViewRect() {
if (viewRect == null || viewRect.width() == 0 || viewRect.height() == 0) {
viewRect = new RectF(0, 0, view.getWidth(), view.getHeight());
}
return viewRect;
}
private void fadeInEffect() {
hasPerformedFadeInAnimation = true;
rectAlpha = 0;
animationInProgress = new Animation() {
@Override protected void applyTransformation(float interpolatedTime, Transformation t) {
rectAlpha = (int) (MAX_RECT_ALPHA * interpolatedTime);
view.invalidate();
}
};
animationInProgress.setInterpolator(new DecelerateInterpolator());
animationInProgress.setDuration(animInDuration);
animationInProgress.setAnimationListener(animationListener);
view.startAnimation(animationInProgress);
}
private void fadeOutEffect() {
hasPerformedFadeInAnimation = false;
animationInProgress = new Animation() {
@Override protected void applyTransformation(float interpolatedTime, Transformation t) {
rectAlpha = MAX_RECT_ALPHA - (int) (MAX_RECT_ALPHA * interpolatedTime);
view.invalidate();
}
};
animationInProgress.setDuration(animOutDuration);
view.startAnimation(animationInProgress);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment