1150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung/* 2150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * Copyright (C) 2010 The Android Open Source Project 3150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * 4150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * Licensed under the Apache License, Version 2.0 (the "License"); 5150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * you may not use this file except in compliance with the License. 6150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * You may obtain a copy of the License at 7150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * 8150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * http://www.apache.org/licenses/LICENSE-2.0 9150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * 10150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * Unless required by applicable law or agreed to in writing, software 11150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * distributed under the License is distributed on an "AS IS" BASIS, 12150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * See the License for the specific language governing permissions and 14150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * limitations under the License. 15150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung */ 16150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung 17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3; 18150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung 194be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.animation.Animator; 204be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.animation.AnimatorListenerAdapter; 21150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chungimport android.animation.ValueAnimator; 22f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurkaimport android.view.View; 23150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung 24150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung/** 25150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * A convenience class for two-way animations, e.g. a fadeIn/fadeOut animation. 26150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * With a regular ValueAnimator, if you call reverse to show the 'out' animation, you'll get 27150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * a frame-by-frame mirror of the 'in' animation -- i.e., the interpolated values will 28150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * be exactly reversed. Using this class, both the 'in' and the 'out' animation use the 29150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * interpolator in the same direction. 30150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung */ 31472b281d5cb4f5660df981a6c912266b9f5703feChet Haasepublic class InterruptibleInOutAnimator { 32150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung private long mOriginalDuration; 33472b281d5cb4f5660df981a6c912266b9f5703feChet Haase private float mOriginalFromValue; 34472b281d5cb4f5660df981a6c912266b9f5703feChet Haase private float mOriginalToValue; 35472b281d5cb4f5660df981a6c912266b9f5703feChet Haase private ValueAnimator mAnimator; 36150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung 374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato private boolean mFirstRun = true; 384be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato 394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato private Object mTag = null; 404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato 41fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy private static final int STOPPED = 0; 42fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy private static final int IN = 1; 43fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy private static final int OUT = 2; 44fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy 4508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy // TODO: This isn't really necessary, but is here to help diagnose a bug in the drag viz 46fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy private int mDirection = STOPPED; 47fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy 48f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka public InterruptibleInOutAnimator(View view, long duration, float fromValue, float toValue) { 49f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka mAnimator = LauncherAnimUtils.ofFloat(view, fromValue, toValue).setDuration(duration); 50150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung mOriginalDuration = duration; 51150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung mOriginalFromValue = fromValue; 52150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung mOriginalToValue = toValue; 5308ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy 548edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka mAnimator.addListener(new AnimatorListenerAdapter() { 553c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka @Override 568edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka public void onAnimationEnd(Animator animation) { 5708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy mDirection = STOPPED; 5808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy } 5908ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy }); 60150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung } 61150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung 62fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy private void animate(int direction) { 63472b281d5cb4f5660df981a6c912266b9f5703feChet Haase final long currentPlayTime = mAnimator.getCurrentPlayTime(); 64472b281d5cb4f5660df981a6c912266b9f5703feChet Haase final float toValue = (direction == IN) ? mOriginalToValue : mOriginalFromValue; 65472b281d5cb4f5660df981a6c912266b9f5703feChet Haase final float startValue = mFirstRun ? mOriginalFromValue : 66472b281d5cb4f5660df981a6c912266b9f5703feChet Haase ((Float) mAnimator.getAnimatedValue()).floatValue(); 67fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy 68fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy // Make sure it's stopped before we modify any values 69150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung cancel(); 70fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy 7108ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy // TODO: We don't really need to do the animation if startValue == toValue, but 7208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy // somehow that doesn't seem to work, possibly a quirk of the animation framework 7308ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy mDirection = direction; 7408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy 7508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy // Ensure we don't calculate a non-sensical duration 7608ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy long duration = mOriginalDuration - currentPlayTime; 7708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy mAnimator.setDuration(Math.max(0, Math.min(duration, mOriginalDuration))); 7808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy 7908ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy mAnimator.setFloatValues(startValue, toValue); 8008ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy mAnimator.start(); 8108ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy mFirstRun = false; 82150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung } 83150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung 84fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy public void cancel() { 85472b281d5cb4f5660df981a6c912266b9f5703feChet Haase mAnimator.cancel(); 86fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy mDirection = STOPPED; 87fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy } 88fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy 89fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy public void end() { 90472b281d5cb4f5660df981a6c912266b9f5703feChet Haase mAnimator.end(); 91fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy mDirection = STOPPED; 92fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy } 93fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy 94fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy /** 95fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy * Return true when the animation is not running and it hasn't even been started. 96fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy */ 97fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy public boolean isStopped() { 98fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy return mDirection == STOPPED; 99fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy } 100fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy 101150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung /** 102150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * This is the equivalent of calling Animator.start(), except that it can be called when 103150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * the animation is running in the opposite direction, in which case we reverse 104150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * direction and animate for a correspondingly shorter duration. 105150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung */ 106150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung public void animateIn() { 107fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy animate(IN); 108150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung } 109150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung 110150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung /** 111150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * This is the roughly the equivalent of calling Animator.reverse(), except that it uses the 112150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * same interpolation curve as animateIn(), rather than mirroring it. Also, like animateIn(), 113150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * if the animation is currently running in the opposite direction, we reverse 114150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung * direction and animate for a correspondingly shorter duration. 115150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung */ 116150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung public void animateOut() { 117fe6bd87881e47b9ff38f58bd083042ae0f6a39d7Patrick Dubroy animate(OUT); 1184be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato } 1194be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato 1204be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato public void setTag(Object tag) { 1214be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato mTag = tag; 1224be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato } 1234be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato 1244be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato public Object getTag() { 1254be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato return mTag; 126150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung } 127472b281d5cb4f5660df981a6c912266b9f5703feChet Haase 128472b281d5cb4f5660df981a6c912266b9f5703feChet Haase public ValueAnimator getAnimator() { 129472b281d5cb4f5660df981a6c912266b9f5703feChet Haase return mAnimator; 130472b281d5cb4f5660df981a6c912266b9f5703feChet Haase } 131150fbab7de7df45ce0e2d08fb0f0be87ff091c2fWinson Chung} 132