Created
July 21, 2017 03:47
-
-
Save brucetoo/be1f09a8bd34938cd6b23eadb9ede6cd to your computer and use it in GitHub Desktop.
ViewAnimator easier
This file contains 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
package com.brucetoo.expandrecyclerview.animator; | |
import android.animation.Animator; | |
import android.animation.ArgbEvaluator; | |
import android.animation.ObjectAnimator; | |
import android.animation.ValueAnimator; | |
import android.support.annotation.IntRange; | |
import android.support.v4.view.ViewCompat; | |
import android.view.View; | |
import android.view.animation.AccelerateInterpolator; | |
import android.view.animation.DecelerateInterpolator; | |
import android.view.animation.Interpolator; | |
import android.widget.TextView; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* Created by Bruce Too | |
* On 12/01/2017. | |
* At 14:22 | |
*/ | |
public class AnimatorBuilder { | |
private final ViewAnimator mViewAnimator; | |
private final View[] mViews; | |
private final List<Animator> mAnimatorList = new ArrayList<>(); | |
private boolean mWaitForSize; | |
private boolean mNextValueWillBeDp = false; | |
/** | |
* Init a new Animation builder with changeable views | |
* | |
* @param viewAnimator the view animator | |
* @param views the animated views | |
*/ | |
public AnimatorBuilder(ViewAnimator viewAnimator, View... views) { | |
this.mViewAnimator = viewAnimator; | |
this.mViews = views; | |
} | |
/** | |
* Make next value be dp in animator builder. | |
* | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder dp() { | |
mNextValueWillBeDp = true; | |
return this; | |
} | |
/** | |
* Add a animator into {@link #mAnimatorList} | |
* | |
* @param animator the animator | |
* @return the animator builder | |
*/ | |
protected AnimatorBuilder add(Animator animator) { | |
this.mAnimatorList.add(animator); | |
return this; | |
} | |
/** | |
* To dp float. | |
* | |
* @param px the px | |
* @return the float | |
*/ | |
protected float toDp(final float px) { | |
return px / mViews[0].getContext().getResources().getDisplayMetrics().density; | |
} | |
/** | |
* To px float. | |
* | |
* @param dp the dp | |
* @return the float | |
*/ | |
protected float toPx(final float dp) { | |
return dp * mViews[0].getContext().getResources().getDisplayMetrics().density; | |
} | |
/** | |
* Get values float [ ]. | |
* | |
* @param values the values | |
* @return the float [ ] | |
*/ | |
protected float[] getValues(float... values) { | |
if (!mNextValueWillBeDp) { | |
return values; | |
} | |
float[] pxValues = new float[values.length]; | |
for (int i = 0; i < values.length; ++i) { | |
pxValues[i] = toPx(values[i]); | |
} | |
return pxValues; | |
} | |
/** | |
* Property animator builder. | |
* | |
* @param propertyName the property name | |
* @param values the values | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder property(String propertyName, float... values) { | |
for (View view : mViews) { | |
this.mAnimatorList.add(ObjectAnimator.ofFloat(view, propertyName, getValues(values))); | |
} | |
return this; | |
} | |
/** | |
* Translation y animator builder. | |
* | |
* @param y the y | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder translationY(float... y) { | |
return property("translationY", y); | |
} | |
/** | |
* Translation x animator builder. | |
* | |
* @param x the x | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder translationX(float... x) { | |
return property("translationX", x); | |
} | |
/** | |
* Alpha animator builder. | |
* | |
* @param alpha the alpha | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder alpha(float... alpha) { | |
return property("alpha", alpha); | |
} | |
/** | |
* Scale x animator builder. | |
* | |
* @param scaleX the scale x | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder scaleX(float... scaleX) { | |
return property("scaleX", scaleX); | |
} | |
/** | |
* Scale y animator builder. | |
* | |
* @param scaleY the scale y | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder scaleY(float... scaleY) { | |
return property("scaleY", scaleY); | |
} | |
/** | |
* Scale animator builder. | |
* | |
* @param scale the scale | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder scale(float... scale) { | |
scaleX(scale); | |
scaleY(scale); | |
return this; | |
} | |
/** | |
* Pivot x animator builder. | |
* | |
* @param pivotX the pivot x | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder pivotX(float pivotX) { | |
for (View view : mViews) { | |
ViewCompat.setPivotX(view, pivotX); | |
} | |
return this; | |
} | |
/** | |
* Pivot y animator builder. | |
* | |
* @param pivotY the pivot y | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder pivotY(float pivotY) { | |
for (View view : mViews) { | |
ViewCompat.setPivotY(view, pivotY); | |
} | |
return this; | |
} | |
public AnimatorBuilder rotationX(float... rotationX) { | |
return property("rotationX", rotationX); | |
} | |
/** | |
* Rotation y animator builder. | |
* | |
* @param rotationY the rotation y | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder rotationY(float... rotationY) { | |
return property("rotationY", rotationY); | |
} | |
/** | |
* Rotation animator builder. | |
* | |
* @param rotation the rotation | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder rotation(float... rotation) { | |
return property("rotation", rotation); | |
} | |
/** | |
* Background color animator builder. | |
* | |
* @param colors the colors | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder backgroundColor(int... colors) { | |
for (View view : mViews) { | |
ObjectAnimator objectAnimator = ObjectAnimator.ofInt(view, "backgroundColor", colors); | |
objectAnimator.setEvaluator(new ArgbEvaluator()); | |
this.mAnimatorList.add(objectAnimator); | |
} | |
return this; | |
} | |
/** | |
* Text color animator builder. | |
* | |
* @param colors the colors | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder textColor(int... colors) { | |
for (View view : mViews) { | |
if (view instanceof TextView) { | |
ObjectAnimator objectAnimator = ObjectAnimator.ofInt(view, "textColor", colors); | |
objectAnimator.setEvaluator(new ArgbEvaluator()); | |
this.mAnimatorList.add(objectAnimator); | |
} | |
} | |
return this; | |
} | |
/** | |
* Custom animator builder. | |
* | |
* @param update the onUpdate | |
* @param values the values | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder custom(final AnimatorListener.Update update, float... values) { | |
for (final View view : mViews) { | |
ValueAnimator valueAnimator = ValueAnimator.ofFloat(getValues(values)); | |
if (update != null) | |
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { | |
@Override | |
public void onAnimationUpdate(ValueAnimator animation) { | |
//noinspection unchecked | |
update.onUpdate(view, (Float) animation.getAnimatedValue()); | |
} | |
}); | |
add(valueAnimator); | |
} | |
return this; | |
} | |
/** | |
* Height animator builder. | |
* | |
* @param height the height | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder height(float... height) { | |
return custom(new AnimatorListener.Update() { | |
@Override | |
public void onUpdate(View view, float value) { | |
view.getLayoutParams().height = (int) value; | |
view.requestLayout(); | |
} | |
}, height); | |
} | |
/** | |
* Width animator builder. | |
* | |
* @param width the width | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder width(float... width) { | |
return custom(new AnimatorListener.Update() { | |
@Override | |
public void onUpdate(View view, float value) { | |
view.getLayoutParams().width = (int) value; | |
view.requestLayout(); | |
} | |
}, width); | |
} | |
/** | |
* Wait for height animator builder. | |
* | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder waitForSize() { | |
mWaitForSize = true; | |
return this; | |
} | |
/** | |
* Get pending animators list. | |
* | |
* @return the list | |
*/ | |
protected List<Animator> getPendingAnimators() { | |
return mAnimatorList; | |
} | |
/** | |
* And animate animator builder. | |
* | |
* @param views the mViews | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder andAnimate(View... views) { | |
return mViewAnimator.addAnimatorBuilder(views); | |
} | |
/** | |
* Then animate animator builder. | |
* | |
* @param views the mViews | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder thenAnimate(View... views) { | |
return mViewAnimator.thenAnimate(views); | |
} | |
/** | |
* Duration view animator. | |
* | |
* @param duration the duration | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder duration(long duration) { | |
mViewAnimator.duration(duration); | |
return this; | |
} | |
/** | |
* Start delay view animator. | |
* | |
* @param startDelay the start delay | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder startDelay(long startDelay) { | |
mViewAnimator.startDelay(startDelay); | |
return this; | |
} | |
/** | |
* Repeat count of animator. | |
* | |
* @param repeatCount the repeat count | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder repeatCount(@IntRange(from = -1) int repeatCount) { | |
mViewAnimator.repeatCount(repeatCount); | |
return this; | |
} | |
/** | |
* Repeat mode view animator. | |
* | |
* @param repeatMode the repeat mode | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder repeatMode(@ViewAnimator.RepeatMode int repeatMode) { | |
mViewAnimator.repeatMode(repeatMode); | |
return this; | |
} | |
/** | |
* On start view animator. | |
* | |
* @param startListener the start listener | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder onStart(AnimatorListener.Start startListener) { | |
mViewAnimator.onStart(startListener); | |
return this; | |
} | |
/** | |
* On stop view animator. | |
* | |
* @param endListener the stop listener | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder onEnd(AnimatorListener.End endListener) { | |
mViewAnimator.onEnd(endListener); | |
return this; | |
} | |
/** | |
* Interpolator for all view animators. | |
* | |
* @param interpolator the interpolator | |
* @return the animator builder | |
*/ | |
public AnimatorBuilder interpolator(Interpolator interpolator) { | |
mViewAnimator.interpolator(interpolator); | |
return this; | |
} | |
/** | |
* Set accelerate interpolator | |
* @return ViewAnimator | |
*/ | |
public ViewAnimator accelerate() { | |
return mViewAnimator.interpolator(new AccelerateInterpolator()); | |
} | |
/** | |
* Set decelerate interpolator | |
* @return ViewAnimator | |
*/ | |
public ViewAnimator decelerate() { | |
return mViewAnimator.interpolator(new DecelerateInterpolator()); | |
} | |
/** | |
* Start current animator | |
*/ | |
public ViewAnimator start() { | |
mViewAnimator.start(); | |
return mViewAnimator; | |
} | |
/** | |
* Get mViews view [ ]. | |
* | |
* @return the view [ ] | |
*/ | |
public View[] getViews() { | |
return mViews; | |
} | |
/** | |
* Wait the view be inflated | |
* | |
* @return the boolean | |
*/ | |
public boolean isWaitForSize() { | |
return mWaitForSize; | |
} | |
} |
This file contains 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
package com.brucetoo.expandrecyclerview.animator; | |
import android.view.View; | |
/** | |
* Created by Bruce Too | |
* On 12/01/2017. | |
* At 14:23 | |
*/ | |
public class AnimatorListener { | |
private AnimatorListener(){} | |
public interface Start{ | |
void onStart(); | |
} | |
public interface End { | |
void onEnd(); | |
} | |
public interface Update<V extends View>{ | |
void onUpdate(V view, float value); | |
} | |
} |
This file contains 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
package com.brucetoo.expandrecyclerview.animator; | |
import android.animation.Animator; | |
import android.animation.AnimatorListenerAdapter; | |
import android.animation.AnimatorSet; | |
import android.animation.ValueAnimator; | |
import android.support.annotation.IntDef; | |
import android.support.annotation.IntRange; | |
import android.support.annotation.NonNull; | |
import android.support.v4.view.ViewCompat; | |
import android.view.View; | |
import android.view.ViewTreeObserver; | |
import android.view.animation.Interpolator; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* Created by Bruce Too | |
* On 12/01/2017. | |
* At 14:20 | |
*/ | |
public class ViewAnimator { | |
private static final long DEFAULT_DURATION = 3000; | |
private List<AnimatorBuilder> mAnimatorBuilderList = new ArrayList<>(); | |
private long mAnimatorDuration = DEFAULT_DURATION; | |
private long mAnimatorStartDelay = 0; | |
private Interpolator mAnimatorInterpolator = null; | |
private int mAnimatorRepeatCount = 0; | |
private int mAnimatorRepeatMode = ValueAnimator.RESTART; | |
private AnimatorSet mAnimatorSet; | |
private View mWaitForThisViewSize = null; | |
private AnimatorListener.Start mStartListener; | |
private AnimatorListener.End mEndListener; | |
private ViewAnimator mPreviousViewAnimator = null; | |
private ViewAnimator mNextViewAnimator = null; | |
private View[] mViews; | |
public ViewAnimator() { | |
} | |
public ViewAnimator(View... view) { | |
this.mViews = view; | |
} | |
@IntDef(value = {ValueAnimator.RESTART, ValueAnimator.REVERSE}) | |
@Retention(RetentionPolicy.SOURCE) | |
public @interface RepeatMode { | |
} | |
/* ----- Set Properties ------*/ | |
public static ViewAnimator putOn(View... view) { | |
return new ViewAnimator(view); | |
} | |
public ViewAnimator andPutOn(View... view) { | |
this.mViews = view; | |
return this; | |
} | |
public ViewAnimator alpha(float alpha) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setAlpha(view, alpha); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator scaleX(float scale) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setScaleX(view, scale); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator scaleY(float scale) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setScaleY(view, scale); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator scale(float scale) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setScaleX(view, scale); | |
ViewCompat.setScaleY(view, scale); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator translationX(float translation) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setTranslationX(view, translation); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator translationY(float translation) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setTranslationY(view, translation); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator translation(float translationX, float translationY) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setTranslationX(view, translationX); | |
ViewCompat.setTranslationY(view, translationY); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator pivotX(float percent) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setPivotX(view, view.getWidth() * percent); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator pivotY(float percent) { | |
if (mViews != null) { | |
for (View view : mViews) { | |
ViewCompat.setPivotY(view, view.getHeight() * percent); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator visible() { | |
if (mViews != null) { | |
for (View view : mViews) { | |
view.setVisibility(View.VISIBLE); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator invisible() { | |
if (mViews != null) { | |
for (View view : mViews) { | |
view.setVisibility(View.INVISIBLE); | |
} | |
} | |
return this; | |
} | |
public ViewAnimator gone() { | |
if (mViews != null) { | |
for (View view : mViews) { | |
view.setVisibility(View.GONE); | |
} | |
} | |
return this; | |
} | |
/* ----- Animator Properties ------*/ | |
/** | |
* Execute animator in views be add by {@link #putOn(View...)} | |
* | |
* @return AnimatorBuilder | |
*/ | |
public AnimatorBuilder animate() { | |
ViewAnimator viewAnimator = new ViewAnimator(); | |
return viewAnimator.addAnimatorBuilder(mViews); | |
} | |
/** | |
* Execute animator in views by given now | |
* | |
* @param views views by animated | |
* @return AnimatorBuilder | |
*/ | |
public static AnimatorBuilder animate(@NonNull View... views) { | |
ViewAnimator viewAnimator = new ViewAnimator(); | |
return viewAnimator.addAnimatorBuilder(views); | |
} | |
public AnimatorBuilder thenAnimate(@NonNull View... views) { | |
ViewAnimator nextViewAnimator = new ViewAnimator(); | |
this.mNextViewAnimator = nextViewAnimator; | |
nextViewAnimator.mPreviousViewAnimator = this; | |
return nextViewAnimator.addAnimatorBuilder(views); | |
} | |
public AnimatorBuilder addAnimatorBuilder(View... views) { | |
AnimatorBuilder animatorBuilder = new AnimatorBuilder(this, views); | |
mAnimatorBuilderList.add(animatorBuilder); | |
return animatorBuilder; | |
} | |
protected AnimatorSet createAnimatorSet() { | |
List<Animator> animators = new ArrayList<>(); | |
//add all pending property animators | |
for (AnimatorBuilder animatorBuilder : mAnimatorBuilderList) { | |
List<Animator> animatorList = animatorBuilder.getPendingAnimators(); | |
animators.addAll(animatorList); | |
} | |
//find if need wait for size | |
for (AnimatorBuilder animatorBuilder : mAnimatorBuilderList) { | |
if (animatorBuilder.isWaitForSize()) { | |
mWaitForThisViewSize = animatorBuilder.getViews()[0]; | |
break; | |
} | |
} | |
//set repeat mode and count if had be set | |
for (Animator animator : animators) { | |
if (animator instanceof ValueAnimator) { | |
ValueAnimator valueAnimator = (ValueAnimator) animator; | |
valueAnimator.setRepeatCount(mAnimatorRepeatCount); | |
valueAnimator.setRepeatMode(mAnimatorRepeatMode); | |
} | |
} | |
AnimatorSet animatorSet = new AnimatorSet(); | |
animatorSet.playTogether(animators); | |
animatorSet.setDuration(mAnimatorDuration); | |
animatorSet.setStartDelay(mAnimatorStartDelay); | |
if (mAnimatorInterpolator != null) | |
animatorSet.setInterpolator(mAnimatorInterpolator); | |
animatorSet.addListener(new AnimatorListenerAdapter() { | |
@Override | |
public void onAnimationStart(Animator animation) { | |
if (mStartListener != null) mStartListener.onStart(); | |
} | |
@Override | |
public void onAnimationEnd(Animator animation) { | |
if (mEndListener != null) mEndListener.onEnd(); | |
if (mNextViewAnimator != null) { | |
mNextViewAnimator.mPreviousViewAnimator = null; | |
mNextViewAnimator.start(); | |
} | |
} | |
}); | |
return animatorSet; | |
} | |
public ViewAnimator start() { | |
if (mPreviousViewAnimator != null) { | |
mPreviousViewAnimator.start(); | |
} else { | |
mAnimatorSet = createAnimatorSet(); | |
if (mWaitForThisViewSize != null) { | |
mWaitForThisViewSize.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { | |
@Override | |
public boolean onPreDraw() { | |
mAnimatorSet.start(); | |
mWaitForThisViewSize.getViewTreeObserver().removeOnPreDrawListener(this); | |
return false; | |
} | |
}); | |
} else { | |
mAnimatorSet.start(); | |
} | |
} | |
return this; | |
} | |
public void cancel() { | |
if (mAnimatorSet != null) { | |
mAnimatorSet.cancel(); | |
} | |
if (mNextViewAnimator != null) { | |
mNextViewAnimator.cancel(); | |
mNextViewAnimator = null; | |
} | |
} | |
public ViewAnimator duration(long duration) { | |
this.mAnimatorDuration = duration; | |
return this; | |
} | |
public ViewAnimator startDelay(long startDelay) { | |
this.mAnimatorStartDelay = startDelay; | |
return this; | |
} | |
/** | |
* Repeat count of animation. | |
* | |
* @param repeatCount the repeat count | |
* @return the view animation | |
*/ | |
public ViewAnimator repeatCount(@IntRange(from = -1) int repeatCount) { | |
this.mAnimatorRepeatCount = repeatCount; | |
return this; | |
} | |
/** | |
* Repeat mode view animation. | |
* | |
* @param repeatMode the repeat mode | |
* @return the view animation | |
*/ | |
public ViewAnimator repeatMode(@RepeatMode int repeatMode) { | |
this.mAnimatorRepeatMode = repeatMode; | |
return this; | |
} | |
public ViewAnimator onStart(AnimatorListener.Start startListener) { | |
this.mStartListener = startListener; | |
return this; | |
} | |
public ViewAnimator onEnd(AnimatorListener.End endListener) { | |
this.mEndListener = endListener; | |
return this; | |
} | |
/** | |
* Interpolator view animator. | |
* | |
* @param interpolator the mAnimatorInterpolator | |
* @return the view animator | |
* @link https://github.com/cimi-chen/EaseInterpolator | |
*/ | |
public ViewAnimator interpolator(Interpolator interpolator) { | |
this.mAnimatorInterpolator = interpolator; | |
return this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment