ValueAnimatorCompatImplEclairMr1.java revision c530cc115fddab8e1d9645b322424dd45f9ecd0d
1/* 2 * Copyright (C) 2015 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 android.support.design.widget; 18 19import android.os.Handler; 20import android.os.Looper; 21import android.os.SystemClock; 22import android.view.animation.AccelerateDecelerateInterpolator; 23import android.view.animation.Interpolator; 24 25/** 26 * A 'fake' ValueAnimator implementation which uses a Runnable. 27 */ 28class ValueAnimatorCompatImplEclairMr1 extends ValueAnimatorCompat.Impl { 29 30 private static final int HANDLER_DELAY = 10; 31 private static final int DEFAULT_DURATION = 200; 32 33 private static final Handler sHandler = new Handler(Looper.getMainLooper()); 34 35 private long mStartTime; 36 private boolean mIsRunning; 37 38 private final int[] mIntValues = new int[2]; 39 private final float[] mFloatValues = new float[2]; 40 41 private int mDuration = DEFAULT_DURATION; 42 private Interpolator mInterpolator; 43 private AnimatorListenerProxy mListener; 44 private AnimatorUpdateListenerProxy mUpdateListener; 45 46 private float mAnimatedFraction; 47 48 @Override 49 public void start() { 50 if (mIsRunning) { 51 // If we're already running, ignore 52 return; 53 } 54 55 if (mInterpolator == null) { 56 mInterpolator = new AccelerateDecelerateInterpolator(); 57 } 58 59 mStartTime = SystemClock.uptimeMillis(); 60 mIsRunning = true; 61 62 // Reset the animated fraction 63 mAnimatedFraction = 0f; 64 65 if (mListener != null) { 66 mListener.onAnimationStart(); 67 } 68 69 sHandler.postDelayed(mRunnable, HANDLER_DELAY); 70 } 71 72 @Override 73 public boolean isRunning() { 74 return mIsRunning; 75 } 76 77 @Override 78 public void setInterpolator(Interpolator interpolator) { 79 mInterpolator = interpolator; 80 } 81 82 @Override 83 public void setListener(AnimatorListenerProxy listener) { 84 mListener = listener; 85 } 86 87 @Override 88 public void setUpdateListener(AnimatorUpdateListenerProxy updateListener) { 89 mUpdateListener = updateListener; 90 } 91 92 @Override 93 public void setIntValues(int from, int to) { 94 mIntValues[0] = from; 95 mIntValues[1] = to; 96 } 97 98 @Override 99 public int getAnimatedIntValue() { 100 return AnimationUtils.lerp(mIntValues[0], mIntValues[1], getAnimatedFraction()); 101 } 102 103 @Override 104 public void setFloatValues(float from, float to) { 105 mFloatValues[0] = from; 106 mFloatValues[1] = to; 107 } 108 109 @Override 110 public float getAnimatedFloatValue() { 111 return AnimationUtils.lerp(mFloatValues[0], mFloatValues[1], getAnimatedFraction()); 112 } 113 114 @Override 115 public void setDuration(int duration) { 116 mDuration = duration; 117 } 118 119 @Override 120 public void cancel() { 121 mIsRunning = false; 122 sHandler.removeCallbacks(mRunnable); 123 124 if (mListener != null) { 125 mListener.onAnimationCancel(); 126 mListener.onAnimationEnd(); 127 } 128 } 129 130 @Override 131 public float getAnimatedFraction() { 132 return mAnimatedFraction; 133 } 134 135 @Override 136 public void end() { 137 if (mIsRunning) { 138 mIsRunning = false; 139 sHandler.removeCallbacks(mRunnable); 140 141 // Set our animated fraction to 1 142 mAnimatedFraction = 1f; 143 144 if (mUpdateListener != null) { 145 mUpdateListener.onAnimationUpdate(); 146 } 147 148 if (mListener != null) { 149 mListener.onAnimationEnd(); 150 } 151 } 152 } 153 154 @Override 155 public long getDuration() { 156 return mDuration; 157 } 158 159 private void update() { 160 if (mIsRunning) { 161 // Update the animated fraction 162 final long elapsed = SystemClock.uptimeMillis() - mStartTime; 163 final float linearFraction = MathUtils.constrain(elapsed / (float) mDuration, 0f, 1f); 164 mAnimatedFraction = mInterpolator != null 165 ? mInterpolator.getInterpolation(linearFraction) 166 : linearFraction; 167 168 // If we're running, dispatch tp the listener 169 if (mUpdateListener != null) { 170 mUpdateListener.onAnimationUpdate(); 171 } 172 173 // Check to see if we've passed the animation duration 174 if (SystemClock.uptimeMillis() >= (mStartTime + mDuration)) { 175 mIsRunning = false; 176 177 if (mListener != null) { 178 mListener.onAnimationEnd(); 179 } 180 } 181 } 182 183 if (mIsRunning) { 184 // If we're still running, post another delayed runnable 185 sHandler.postDelayed(mRunnable, HANDLER_DELAY); 186 } 187 } 188 189 private final Runnable mRunnable = new Runnable() { 190 public void run() { 191 update(); 192 } 193 }; 194} 195