diff options
Diffstat (limited to 'src/com/android/launcher3/InterruptibleInOutAnimator.java')
-rw-r--r-- | src/com/android/launcher3/InterruptibleInOutAnimator.java | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/com/android/launcher3/InterruptibleInOutAnimator.java b/src/com/android/launcher3/InterruptibleInOutAnimator.java new file mode 100644 index 000000000..2898b347d --- /dev/null +++ b/src/com/android/launcher3/InterruptibleInOutAnimator.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.view.View; + +/** + * A convenience class for two-way animations, e.g. a fadeIn/fadeOut animation. + * With a regular ValueAnimator, if you call reverse to show the 'out' animation, you'll get + * a frame-by-frame mirror of the 'in' animation -- i.e., the interpolated values will + * be exactly reversed. Using this class, both the 'in' and the 'out' animation use the + * interpolator in the same direction. + */ +public class InterruptibleInOutAnimator { + private long mOriginalDuration; + private float mOriginalFromValue; + private float mOriginalToValue; + private ValueAnimator mAnimator; + + private boolean mFirstRun = true; + + private Object mTag = null; + + private static final int STOPPED = 0; + private static final int IN = 1; + private static final int OUT = 2; + + // TODO: This isn't really necessary, but is here to help diagnose a bug in the drag viz + private int mDirection = STOPPED; + + public InterruptibleInOutAnimator(View view, long duration, float fromValue, float toValue) { + mAnimator = LauncherAnimUtils.ofFloat(view, fromValue, toValue).setDuration(duration); + mOriginalDuration = duration; + mOriginalFromValue = fromValue; + mOriginalToValue = toValue; + + mAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mDirection = STOPPED; + } + }); + } + + private void animate(int direction) { + final long currentPlayTime = mAnimator.getCurrentPlayTime(); + final float toValue = (direction == IN) ? mOriginalToValue : mOriginalFromValue; + final float startValue = mFirstRun ? mOriginalFromValue : + ((Float) mAnimator.getAnimatedValue()).floatValue(); + + // Make sure it's stopped before we modify any values + cancel(); + + // TODO: We don't really need to do the animation if startValue == toValue, but + // somehow that doesn't seem to work, possibly a quirk of the animation framework + mDirection = direction; + + // Ensure we don't calculate a non-sensical duration + long duration = mOriginalDuration - currentPlayTime; + mAnimator.setDuration(Math.max(0, Math.min(duration, mOriginalDuration))); + + mAnimator.setFloatValues(startValue, toValue); + mAnimator.start(); + mFirstRun = false; + } + + public void cancel() { + mAnimator.cancel(); + mDirection = STOPPED; + } + + public void end() { + mAnimator.end(); + mDirection = STOPPED; + } + + /** + * Return true when the animation is not running and it hasn't even been started. + */ + public boolean isStopped() { + return mDirection == STOPPED; + } + + /** + * This is the equivalent of calling Animator.start(), except that it can be called when + * the animation is running in the opposite direction, in which case we reverse + * direction and animate for a correspondingly shorter duration. + */ + public void animateIn() { + animate(IN); + } + + /** + * This is the roughly the equivalent of calling Animator.reverse(), except that it uses the + * same interpolation curve as animateIn(), rather than mirroring it. Also, like animateIn(), + * if the animation is currently running in the opposite direction, we reverse + * direction and animate for a correspondingly shorter duration. + */ + public void animateOut() { + animate(OUT); + } + + public void setTag(Object tag) { + mTag = tag; + } + + public Object getTag() { + return mTag; + } + + public ValueAnimator getAnimator() { + return mAnimator; + } +} |