1631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes/* 2631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * Copyright (C) 2015 The Android Open Source Project 3631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * 4631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 5631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * you may not use this file except in compliance with the License. 6631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * You may obtain a copy of the License at 7631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * 8631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * http://www.apache.org/licenses/LICENSE-2.0 9631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * 10631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * Unless required by applicable law or agreed to in writing, software 11631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * distributed under the License is distributed on an "AS IS" BASIS, 12631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * See the License for the specific language governing permissions and 14631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * limitations under the License. 15631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes */ 16631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 17631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banespackage android.support.design.widget; 18631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 19631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banesimport android.os.Handler; 20631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banesimport android.os.Looper; 21631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banesimport android.os.SystemClock; 22631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banesimport android.view.animation.AccelerateDecelerateInterpolator; 23631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banesimport android.view.animation.Interpolator; 24631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 25631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes/** 26631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes * A 'fake' ValueAnimator implementation which uses a Runnable. 27631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes */ 28631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banesclass ValueAnimatorCompatImplEclairMr1 extends ValueAnimatorCompat.Impl { 29631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 30631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private static final int HANDLER_DELAY = 10; 31631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private static final int DEFAULT_DURATION = 200; 32631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 33631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private static final Handler sHandler = new Handler(Looper.getMainLooper()); 34631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 35631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private long mStartTime; 36631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private boolean mIsRunning; 37631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 38631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private final int[] mIntValues = new int[2]; 39631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private final float[] mFloatValues = new float[2]; 40631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 41631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private int mDuration = DEFAULT_DURATION; 42631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private Interpolator mInterpolator; 43631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private AnimatorListenerProxy mListener; 44631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private AnimatorUpdateListenerProxy mUpdateListener; 45631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 46631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private float mAnimatedFraction; 47631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 48631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 49631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void start() { 50631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mIsRunning) { 51631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // If we're already running, ignore 52631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return; 53631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 54631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 55631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mInterpolator == null) { 56631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mInterpolator = new AccelerateDecelerateInterpolator(); 57631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 58631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 59631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mStartTime = SystemClock.uptimeMillis(); 60631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIsRunning = true; 61631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 62631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mListener != null) { 63631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener.onAnimationStart(); 64631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 65631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 66631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes sHandler.postDelayed(mRunnable, HANDLER_DELAY); 67631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 68631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 69631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 70631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public boolean isRunning() { 71631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return mIsRunning; 72631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 73631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 74631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 75631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setInterpolator(Interpolator interpolator) { 76631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mInterpolator = interpolator; 77631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 78631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 79631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 80631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setListener(AnimatorListenerProxy listener) { 81631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener = listener; 82631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 83631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 84631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 85631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setUpdateListener(AnimatorUpdateListenerProxy updateListener) { 86631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mUpdateListener = updateListener; 87631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 88631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 89631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 90631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setIntValues(int from, int to) { 91631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIntValues[0] = from; 92631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIntValues[1] = to; 93631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 94631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 95631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 96631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public int getAnimatedIntValue() { 97631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return AnimationUtils.lerp(mIntValues[0], mIntValues[1], getAnimatedFraction()); 98631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 99631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 100631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 101631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setFloatValues(float from, float to) { 102631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mFloatValues[0] = from; 103631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mFloatValues[1] = to; 104631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 105631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 106631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 107631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public float getAnimatedFloatValue() { 108631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return AnimationUtils.lerp(mFloatValues[0], mFloatValues[1], getAnimatedFraction()); 109631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 110631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 111631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 112631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setDuration(int duration) { 113631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mDuration = duration; 114631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 115631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 116631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 117631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void cancel() { 118631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIsRunning = false; 119631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes sHandler.removeCallbacks(mRunnable); 120631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 121631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mListener != null) { 122631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener.onAnimationCancel(); 123631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 124631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 125631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 126631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 127631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public float getAnimatedFraction() { 128631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return mAnimatedFraction; 129631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 130631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 131631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 132631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void end() { 133631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mIsRunning) { 134631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIsRunning = false; 135631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes sHandler.removeCallbacks(mRunnable); 136631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 137631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // Set our animated fraction to 1 138631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mAnimatedFraction = 1f; 139631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 140631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mUpdateListener != null) { 141631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mUpdateListener.onAnimationUpdate(); 142631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 143631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 144631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mListener != null) { 145631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener.onAnimationEnd(); 146631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 147631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 148631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 149631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 150631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private void update() { 151631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mIsRunning) { 152631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // Update the animated fraction 153631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes final long elapsed = SystemClock.uptimeMillis() - mStartTime; 154631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes final float linearFraction = elapsed / (float) mDuration; 155631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mAnimatedFraction = mInterpolator != null 156631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes ? mInterpolator.getInterpolation(linearFraction) 157631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes : linearFraction; 158631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 159631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // If we're running, dispatch tp the listener 160631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mUpdateListener != null) { 161631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mUpdateListener.onAnimationUpdate(); 162631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 163631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 164631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // Check to see if we've passed the animation duration 165631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (SystemClock.uptimeMillis() >= (mStartTime + mDuration)) { 166631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIsRunning = false; 167631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 168631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mListener != null) { 169631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener.onAnimationEnd(); 170631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 171631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 172631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 173631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 174631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mIsRunning) { 175631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // If we're still running, post another delayed runnable 176631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes sHandler.postDelayed(mRunnable, HANDLER_DELAY); 177631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 178631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 179631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 180631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private final Runnable mRunnable = new Runnable() { 181631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void run() { 182631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes update(); 183631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 184631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes }; 185631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes} 186