package com.kaichunlin.transition.internal; import android.support.annotation.CheckResult; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.View; import android.view.animation.Interpolator; import com.kaichunlin.transition.R; import com.kaichunlin.transition.TransitionConfig; import com.kaichunlin.transition.TransitionManager; import com.kaichunlin.transition.util.TransitionStateLogger; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.AnimatorSet; import java.util.ArrayList; import java.util.List; /** * Manages the transition state of a set of {@link TransitionController} as a single unit. */ public class TransitionControllerManager implements Cloneable { private List<TransitionController> mTransitionControls = new ArrayList<>(); private Interpolator mInterpolator; private String mId; private View mTarget; float mLastProgress; private boolean mUpdateStateAfterUpdateProgress; public TransitionControllerManager(String id) { mId = id; } /** * Adds an Animator as {@link TransitionController} * * @param mAnim * @return */ public TransitionController addAnimatorAsTransition(@NonNull Animator mAnim) { AnimatorSet as = new AnimatorSet(); as.play(mAnim); return addAnimatorSetAsTransition(null, as); } /** * Adds an Animator as {@link TransitionController} * * @param target * @param animator * @return */ public TransitionController addAnimatorAsTransition(@Nullable View target, @NonNull Animator animator) { AnimatorSet as = new AnimatorSet(); as.play(animator); return addAnimatorSetAsTransition(target, as); } /** * Adds an AnimatorSet as {@link TransitionController} * * @param animatorSet * @return */ public TransitionController addAnimatorSetAsTransition(@NonNull AnimatorSet animatorSet) { return addAnimatorSetAsTransition(null, animatorSet); } /** * Adds an AnimatorSet as {@link TransitionController} * * @param target * @param animatorSet * @return */ public TransitionController addAnimatorSetAsTransition(@Nullable View target, @NonNull AnimatorSet animatorSet) { return addTransitionController(new DefaultTransitionController(target, animatorSet)); } /** * @param transitionController the TransitionController to be managed by this object * @return */ public TransitionController addTransitionController(@NonNull TransitionController transitionController) { transitionController.setId(mId); boolean changed = false; if (!mTransitionControls.contains(transitionController)) { mTransitionControls.add(transitionController); changed = true; } if (!changed && TransitionConfig.isDebug()) { getTransitionStateHolder().append(mId + "->" + mTarget, this, "Possible duplicate: " + transitionController.getId()); } return transitionController; } /** * Starts the transition */ public void start() { if (TransitionConfig.isDebug()) { getTransitionStateHolder().start(); } mLastProgress = Float.MIN_VALUE; TransitionController transitionController; for (int i = 0, size = mTransitionControls.size(); i < size; i++) { transitionController = mTransitionControls.get(i); if (mInterpolator != null) { transitionController.setInterpolator(mInterpolator); } //required for ViewPager transitions to work if (mTarget != null) { transitionController.setTarget(mTarget); } transitionController.setUpdateStateAfterUpdateProgress(mUpdateStateAfterUpdateProgress); transitionController.start(); } } private TransitionStateLogger getTransitionStateHolder() { return (TransitionStateLogger) getTarget().getTag(R.id.debug_id); } private String getTransitionStateHolderId() { return ((TransitionStateLogger) getTarget().getTag(R.id.debug_id)).mId; } /** * Ends the transition */ public void end() { if (TransitionConfig.isPrintDebug()) { getTransitionStateHolder().end(); getTransitionStateHolder().print(); } for (int i = 0, size = mTransitionControls.size(); i < size; i++) { mTransitionControls.get(i).end(); } } /** * Updates the transition progress * * @param progress the possible range of values depends on the {@link TransitionManager} being used */ public void updateProgress(float progress) { if (mLastProgress == progress) { return; } mLastProgress = progress; //TODO this makes ViewPager work, but will probably break more complex transition setup, will think of a better solution if (mUpdateStateAfterUpdateProgress) { boolean positive = progress >= 0; TransitionController transitionController; for (int i = 0, size = mTransitionControls.size(); i < size; i++) { transitionController = mTransitionControls.get(i); if (positive) { if (transitionController.getEnd() > 0) { transitionController.setEnable(true); } else { transitionController.setEnable(false); } } else { if (transitionController.getEnd() < 0) { transitionController.setEnable(true); } else { transitionController.setEnable(false); } } } } TransitionController transitionController; for (int i = 0, size = mTransitionControls.size(); i < size; i++) { transitionController = mTransitionControls.get(i); if (transitionController.isEnable()) { transitionController.updateProgress(progress); } } } /** * @param target the view that all {@link TransitionController} managed by this object should work on */ public void setTarget(@Nullable View target) { mTarget = target; for (int i = 0, size = mTransitionControls.size(); i < size; i++) { mTransitionControls.get(i).setTarget(target); } } /** * @return */ @Nullable public View getTarget() { return mTarget; } /** * Reverses all the TransitionControllers managed by this TransitionManager */ public void reverse() { for (int i = 0, size = mTransitionControls.size(); i < size; i++) { mTransitionControls.get(i).reverse(); } } /** * @param interpolator the Interpolator to be applied to all {@link TransitionController} managed by this object */ public void setInterpolator(@Nullable Interpolator interpolator) { mInterpolator = interpolator; } /** * @param updateStateAfterUpdateProgress whether or not to update a controller's enable state after each {@link #updateProgress(float)} call */ public void setUpdateStateAfterUpdateProgress(boolean updateStateAfterUpdateProgress) { mUpdateStateAfterUpdateProgress = updateStateAfterUpdateProgress; } @CheckResult @Override public TransitionControllerManager clone() { TransitionControllerManager newClone = null; try { newClone = (TransitionControllerManager) super.clone(); newClone.mTransitionControls = new ArrayList<>(mTransitionControls.size()); for (int i = 0, size = mTransitionControls.size(); i < size; i++) { newClone.mTransitionControls.add(mTransitionControls.get(i).clone()); } } catch (CloneNotSupportedException e) { e.printStackTrace(); } return newClone; } }