-
-
Save yiranshaxiao/0278ab82444a8180f0e082e8ebecb28e to your computer and use it in GitHub Desktop.
A simple drawable wrapper with scale animation on Android
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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