blob: 1c708f57c9c1bc08c12a41e3934f2287a7f4ec58 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.design.widget;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
/**
* A 'fake' ValueAnimator implementation which uses a Runnable.
*/
class ValueAnimatorCompatImplEclairMr1 extends ValueAnimatorCompat.Impl {
private static final int HANDLER_DELAY = 10;
private static final int DEFAULT_DURATION = 200;
private static final Handler sHandler = new Handler(Looper.getMainLooper());
private long mStartTime;
private boolean mIsRunning;
private final int[] mIntValues = new int[2];
private final float[] mFloatValues = new float[2];
private int mDuration = DEFAULT_DURATION;
private Interpolator mInterpolator;
private AnimatorListenerProxy mListener;
private AnimatorUpdateListenerProxy mUpdateListener;
private float mAnimatedFraction;
@Override
public void start() {
if (mIsRunning) {
// If we're already running, ignore
return;
}
if (mInterpolator == null) {
mInterpolator = new AccelerateDecelerateInterpolator();
}
mStartTime = SystemClock.uptimeMillis();
mIsRunning = true;
if (mListener != null) {
mListener.onAnimationStart();
}
sHandler.postDelayed(mRunnable, HANDLER_DELAY);
}
@Override
public boolean isRunning() {
return mIsRunning;
}
@Override
public void setInterpolator(Interpolator interpolator) {
mInterpolator = interpolator;
}
@Override
public void setListener(AnimatorListenerProxy listener) {
mListener = listener;
}
@Override
public void setUpdateListener(AnimatorUpdateListenerProxy updateListener) {
mUpdateListener = updateListener;
}
@Override
public void setIntValues(int from, int to) {
mIntValues[0] = from;
mIntValues[1] = to;
}
@Override
public int getAnimatedIntValue() {
return AnimationUtils.lerp(mIntValues[0], mIntValues[1], getAnimatedFraction());
}
@Override
public void setFloatValues(float from, float to) {
mFloatValues[0] = from;
mFloatValues[1] = to;
}
@Override
public float getAnimatedFloatValue() {
return AnimationUtils.lerp(mFloatValues[0], mFloatValues[1], getAnimatedFraction());
}
@Override
public void setDuration(int duration) {
mDuration = duration;
}
@Override
public void cancel() {
mIsRunning = false;
sHandler.removeCallbacks(mRunnable);
if (mListener != null) {
mListener.onAnimationCancel();
}
}
@Override
public float getAnimatedFraction() {
return mAnimatedFraction;
}
@Override
public void end() {
if (mIsRunning) {
mIsRunning = false;
sHandler.removeCallbacks(mRunnable);
// Set our animated fraction to 1
mAnimatedFraction = 1f;
if (mUpdateListener != null) {
mUpdateListener.onAnimationUpdate();
}
if (mListener != null) {
mListener.onAnimationEnd();
}
}
}
@Override
public long getDuration() {
return mDuration;
}
private void update() {
if (mIsRunning) {
// Update the animated fraction
final long elapsed = SystemClock.uptimeMillis() - mStartTime;
final float linearFraction = elapsed / (float) mDuration;
mAnimatedFraction = mInterpolator != null
? mInterpolator.getInterpolation(linearFraction)
: linearFraction;
// If we're running, dispatch tp the listener
if (mUpdateListener != null) {
mUpdateListener.onAnimationUpdate();
}
// Check to see if we've passed the animation duration
if (SystemClock.uptimeMillis() >= (mStartTime + mDuration)) {
mIsRunning = false;
if (mListener != null) {
mListener.onAnimationEnd();
}
}
}
if (mIsRunning) {
// If we're still running, post another delayed runnable
sHandler.postDelayed(mRunnable, HANDLER_DELAY);
}
}
private final Runnable mRunnable = new Runnable() {
public void run() {
update();
}
};
}