InterruptibleInOutAnimator.java revision 3c4c20fbe682cb4b3ef94f09afe0af09171583f3
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.launcher2; 18 19import android.animation.Animator; 20import android.animation.AnimatorListenerAdapter; 21import android.animation.ObjectAnimator; 22import android.animation.ValueAnimator; 23import android.util.Log; 24 25/** 26 * A convenience class for two-way animations, e.g. a fadeIn/fadeOut animation. 27 * With a regular ValueAnimator, if you call reverse to show the 'out' animation, you'll get 28 * a frame-by-frame mirror of the 'in' animation -- i.e., the interpolated values will 29 * be exactly reversed. Using this class, both the 'in' and the 'out' animation use the 30 * interpolator in the same direction. 31 */ 32public class InterruptibleInOutAnimator { 33 private long mOriginalDuration; 34 private float mOriginalFromValue; 35 private float mOriginalToValue; 36 private ValueAnimator mAnimator; 37 38 private boolean mFirstRun = true; 39 40 private Object mTag = null; 41 42 private static final int STOPPED = 0; 43 private static final int IN = 1; 44 private static final int OUT = 2; 45 46 // TODO: This isn't really necessary, but is here to help diagnose a bug in the drag viz 47 private int mDirection = STOPPED; 48 49 public InterruptibleInOutAnimator(long duration, float fromValue, float toValue) { 50 mAnimator = ValueAnimator.ofFloat(fromValue, toValue).setDuration(duration); 51 mOriginalDuration = duration; 52 mOriginalFromValue = fromValue; 53 mOriginalToValue = toValue; 54 55 mAnimator.addListener(new LauncherAnimatorListenerAdapter() { 56 @Override 57 public void onAnimationEndOrCancel(Animator animation) { 58 mDirection = STOPPED; 59 } 60 }); 61 } 62 63 private void animate(int direction) { 64 final long currentPlayTime = mAnimator.getCurrentPlayTime(); 65 final float toValue = (direction == IN) ? mOriginalToValue : mOriginalFromValue; 66 final float startValue = mFirstRun ? mOriginalFromValue : 67 ((Float) mAnimator.getAnimatedValue()).floatValue(); 68 69 // Make sure it's stopped before we modify any values 70 cancel(); 71 72 // TODO: We don't really need to do the animation if startValue == toValue, but 73 // somehow that doesn't seem to work, possibly a quirk of the animation framework 74 mDirection = direction; 75 76 // Ensure we don't calculate a non-sensical duration 77 long duration = mOriginalDuration - currentPlayTime; 78 mAnimator.setDuration(Math.max(0, Math.min(duration, mOriginalDuration))); 79 80 mAnimator.setFloatValues(startValue, toValue); 81 mAnimator.start(); 82 mFirstRun = false; 83 } 84 85 public void cancel() { 86 mAnimator.cancel(); 87 mDirection = STOPPED; 88 } 89 90 public void end() { 91 mAnimator.end(); 92 mDirection = STOPPED; 93 } 94 95 /** 96 * Return true when the animation is not running and it hasn't even been started. 97 */ 98 public boolean isStopped() { 99 return mDirection == STOPPED; 100 } 101 102 /** 103 * This is the equivalent of calling Animator.start(), except that it can be called when 104 * the animation is running in the opposite direction, in which case we reverse 105 * direction and animate for a correspondingly shorter duration. 106 */ 107 public void animateIn() { 108 animate(IN); 109 } 110 111 /** 112 * This is the roughly the equivalent of calling Animator.reverse(), except that it uses the 113 * same interpolation curve as animateIn(), rather than mirroring it. Also, like animateIn(), 114 * if the animation is currently running in the opposite direction, we reverse 115 * direction and animate for a correspondingly shorter duration. 116 */ 117 public void animateOut() { 118 animate(OUT); 119 } 120 121 public void setTag(Object tag) { 122 mTag = tag; 123 } 124 125 public Object getTag() { 126 return mTag; 127 } 128 129 public ValueAnimator getAnimator() { 130 return mAnimator; 131 } 132} 133