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 41e852801f9258e00f89da48918b58a6e933643ab9Aurimas Liutikas private long 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 62c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov // Reset the animated fraction 63c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov mAnimatedFraction = 0f; 64c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov 65631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mListener != null) { 66631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener.onAnimationStart(); 67631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 68631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 69631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes sHandler.postDelayed(mRunnable, HANDLER_DELAY); 70631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 71631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 72631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 73631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public boolean isRunning() { 74631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return mIsRunning; 75631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 76631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 77631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 78631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setInterpolator(Interpolator interpolator) { 79631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mInterpolator = interpolator; 80631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 81631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 82631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 83631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setListener(AnimatorListenerProxy listener) { 84631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener = listener; 85631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 86631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 87631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 88631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setUpdateListener(AnimatorUpdateListenerProxy updateListener) { 89631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mUpdateListener = updateListener; 90631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 91631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 92631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 93631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setIntValues(int from, int to) { 94631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIntValues[0] = from; 95631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIntValues[1] = to; 96631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 97631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 98631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 99631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public int getAnimatedIntValue() { 100631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return AnimationUtils.lerp(mIntValues[0], mIntValues[1], getAnimatedFraction()); 101631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 102631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 103631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 104631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void setFloatValues(float from, float to) { 105631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mFloatValues[0] = from; 106631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mFloatValues[1] = to; 107631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 108631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 109631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 110631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public float getAnimatedFloatValue() { 111631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return AnimationUtils.lerp(mFloatValues[0], mFloatValues[1], getAnimatedFraction()); 112631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 113631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 114631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 115e852801f9258e00f89da48918b58a6e933643ab9Aurimas Liutikas public void setDuration(long duration) { 116631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mDuration = duration; 117631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 118631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 119631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 120631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void cancel() { 121631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIsRunning = false; 122631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes sHandler.removeCallbacks(mRunnable); 123631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 124631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mListener != null) { 125631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener.onAnimationCancel(); 126c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov mListener.onAnimationEnd(); 127631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 128631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 129631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 130631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 131631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public float getAnimatedFraction() { 132631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes return mAnimatedFraction; 133631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 134631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 135631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes @Override 136631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void end() { 137631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mIsRunning) { 138631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIsRunning = false; 139631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes sHandler.removeCallbacks(mRunnable); 140631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 141631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // Set our animated fraction to 1 142631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mAnimatedFraction = 1f; 143631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 144631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mUpdateListener != null) { 145631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mUpdateListener.onAnimationUpdate(); 146631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 147631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 148631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mListener != null) { 149631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener.onAnimationEnd(); 150631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 151631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 152631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 153631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 154ba2a96aaf54f6fc755856ef05a3c967a5f000b82Chris Banes @Override 155ba2a96aaf54f6fc755856ef05a3c967a5f000b82Chris Banes public long getDuration() { 156ba2a96aaf54f6fc755856ef05a3c967a5f000b82Chris Banes return mDuration; 157ba2a96aaf54f6fc755856ef05a3c967a5f000b82Chris Banes } 158ba2a96aaf54f6fc755856ef05a3c967a5f000b82Chris Banes 159631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private void update() { 160631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mIsRunning) { 161631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // Update the animated fraction 162631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes final long elapsed = SystemClock.uptimeMillis() - mStartTime; 163c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov final float linearFraction = MathUtils.constrain(elapsed / (float) mDuration, 0f, 1f); 164631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mAnimatedFraction = mInterpolator != null 165631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes ? mInterpolator.getInterpolation(linearFraction) 166631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes : linearFraction; 167631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 168631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // If we're running, dispatch tp the listener 169631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mUpdateListener != null) { 170631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mUpdateListener.onAnimationUpdate(); 171631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 172631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 173631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // Check to see if we've passed the animation duration 174631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (SystemClock.uptimeMillis() >= (mStartTime + mDuration)) { 175631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mIsRunning = false; 176631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 177631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mListener != null) { 178631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes mListener.onAnimationEnd(); 179631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 180631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 181631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 182631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 183631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes if (mIsRunning) { 184631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes // If we're still running, post another delayed runnable 185631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes sHandler.postDelayed(mRunnable, HANDLER_DELAY); 186631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 187631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 188631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes 189631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes private final Runnable mRunnable = new Runnable() { 190631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes public void run() { 191631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes update(); 192631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes } 193631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes }; 194631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes} 195