package com.kaichunlin.transition.animation; import android.animation.ValueAnimator; import android.os.Build; import android.view.animation.LinearInterpolator; import java.util.ArrayList; import java.util.List; /** * Uses a {@link android.animation.ValueAnimator} as the control to drive the animation, used by * {@link AnimationManager} and {@link TransitionAnimation}. For some reason changing the layout with * ValueAnimator is very slow so {@link AnimationController} should be used instead, unless * {@link #pauseController()} and {@link #resumeController()} functions are needed. */ class AnimatorController extends ValueAnimator implements StateController, ValueAnimator.AnimatorUpdateListener, android.animation.Animator.AnimatorListener { private final List<AbstractAnimation> mAnimationList = new ArrayList<>(); private boolean mReset; private boolean mCancel; /** * * @param reverse Whether or not to reverse the animation. */ AnimatorController(boolean reverse) { setInterpolator(new LinearInterpolator()); if (reverse) { setFloatValues(1, 0); } else { setFloatValues(0, 1); } addUpdateListener(this); addListener(this); } @Override public void addAnimation(AbstractAnimation animatorStateListener) { mAnimationList.add(animatorStateListener); } @Override public void setAnimationDuration(long duration) { setDuration(duration); } @Override public void startController() { start(); mReset = false; mCancel = false; } @Override public void pauseController() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } pause(); } @Override public void resumeController() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } resume(); } @Override public void endController() { end(); } @Override public void resetController() { mReset = true; AbstractAnimation ani; for (int i = 0, size = mAnimationList.size(); i < size; i++) { ani = mAnimationList.get(i); ani.notifyAnimationReset(); } cancel(); //TODO optimize for (int i = 0, size = mAnimationList.size(); i < size; i++) { ani = mAnimationList.get(i); ani.getTransition().startTransition(); ani.getTransition().updateProgress(ani.isReverseAnimation() ? 1 : 0); ani.getTransition().stopTransition(); } } @Override public void cancelController() { cancel(); } @Override public void onAnimationUpdate(ValueAnimator animation) { AbstractAnimation ani; float progress = (Float) animation.getAnimatedValue(); for (int i = 0, size = mAnimationList.size(); i < size; i++) { ani = mAnimationList.get(i); ani.getTransition().updateProgress(progress); } } @Override public void onAnimationStart(android.animation.Animator animation) { for (int i = 0, size = mAnimationList.size(); i < size; i++) { mAnimationList.get(i).notifyAnimationStart(); } } @Override public void onAnimationEnd(android.animation.Animator animation) { if (mReset || mCancel) { return; } AbstractAnimation ani; for (int i = 0, size = mAnimationList.size(); i < size; i++) { ani = mAnimationList.get(i); ani.setAnimating(false); ani.notifyAnimationEnd(); ani.getTransition().stopTransition(); } } @Override public void onAnimationCancel(android.animation.Animator animation) { AbstractAnimation ani; for (int i = 0, size = mAnimationList.size(); i < size; i++) { ani = mAnimationList.get(i); if (mReset) { ani.notifyAnimationReset(); } else { ani.notifyAnimationCancel(); } ani.setAnimating(false); ani.getTransition().stopTransition(); } mCancel = true; } @Override public void onAnimationRepeat(android.animation.Animator animation) { } }