Skip to content

Instantly share code, notes, and snippets.

@vahid-m
Forked from yiranshaxiao/java
Created March 19, 2024 13:24
Show Gist options
  • Save vahid-m/c7b1f84e2430e1b7e9a7f2b6bcb24397 to your computer and use it in GitHub Desktop.
Save vahid-m/c7b1f84e2430e1b7e9a7f2b6bcb24397 to your computer and use it in GitHub Desktop.
A simple drawable wrapper with scale animation on Android
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v7.graphics.drawable.DrawableWrapper;
import android.util.Property;
import android.view.animation.BounceInterpolator;
import android.view.animation.LinearInterpolator;
import java.util.Arrays;
public class AnimateDrawable extends DrawableWrapper {
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
private static final TimeInterpolator BOUNCE_INTERPOLATOR = new BounceInterpolator();
private static final float ORIGIN_SCALE = 1.0f;
private static final float DEFAULT_SCALE_DOWN = 0.95f;
private static final FloatProperty<AnimateDrawable> SCALE = new FloatProperty<AnimateDrawable>("scaleY") {
@Override
public void setValue(AnimateDrawable object, float value) {
object.mScale = value;
object.invalidateSelf();
}
@Override
public Float get(AnimateDrawable object) {
return object.mScale;
}
};
private float mScale = ORIGIN_SCALE;
private boolean mActive = false;
private AnimatorSet mDownScaleAnimatorSet;
private AnimatorSet mUpScaleAnimatorSet;
public AnimateDrawable(Drawable drawable) {
super(drawable);
}
@Override
public boolean isStateful() {
return true;
}
@Override
public boolean setState(int[] stateSet) {
if (!Arrays.equals(getWrappedDrawable().getState(), stateSet)) {
getWrappedDrawable().setState(stateSet);
return onStateChange(stateSet);
}
return false;
}
@Override
protected boolean onStateChange(int[] stateSet) {
final boolean changed = super.onStateChange(stateSet);
boolean enabled = false;
boolean pressed = false;
for (int state : stateSet) {
if (state == android.R.attr.state_enabled) {
enabled = true;
} else if (state == android.R.attr.state_pressed) {
pressed = true;
}
}
setScaleActive(enabled && pressed);
return changed;
}
private void setScaleActive(boolean active) {
if (mActive != active) {
mActive = active;
if (active) {
tryScaleDown();
} else {
tryScaleUp();
}
}
}
public void cancel() {
if (mDownScaleAnimatorSet != null) {
mDownScaleAnimatorSet.cancel();
}
if (mUpScaleAnimatorSet != null) {
mUpScaleAnimatorSet.cancel();
}
}
private void tryScaleDown() {
cancel();
mDownScaleAnimatorSet = new AnimatorSet();
final ObjectAnimator scale = ObjectAnimator.ofFloat(this, SCALE, ORIGIN_SCALE, DEFAULT_SCALE_DOWN);
if (Build.VERSION.SDK_INT >= 18) {
scale.setAutoCancel(true);
}
mDownScaleAnimatorSet.setInterpolator(LINEAR_INTERPOLATOR);
mDownScaleAnimatorSet.setDuration(200);
mDownScaleAnimatorSet.play(scale);
mDownScaleAnimatorSet.start();
}
private void tryScaleUp() {
cancel();
mUpScaleAnimatorSet = new AnimatorSet();
final ObjectAnimator scale = ObjectAnimator.ofFloat(this, SCALE, DEFAULT_SCALE_DOWN, ORIGIN_SCALE);
if (Build.VERSION.SDK_INT >= 18) {
scale.setAutoCancel(true);
}
mUpScaleAnimatorSet.setInterpolator(BOUNCE_INTERPOLATOR);
mUpScaleAnimatorSet.setDuration(200);
mUpScaleAnimatorSet.play(scale);
mUpScaleAnimatorSet.start();
}
@Override
public void draw(Canvas canvas) {
canvas.scale(mScale, mScale, canvas.getWidth() / 2, canvas.getHeight() / 2);
super.draw(canvas);
}
public static abstract class FloatProperty<T> extends Property<T, Float> {
public FloatProperty(String name) {
super(Float.class, name);
}
/**
* A type-specific variant of {@link #set(Object, Float)} that is faster when dealing
* with fields of type <code>float</code>.
*/
public abstract void setValue(T object, float value);
@Override
final public void set(T object, Float value) {
setValue(object, value);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment