/* * Copyright 2013 Chris Banes * * 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 uk.co.senab.actionbarpulltorefresh.library.widget; import android.view.View; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import uk.co.senab.actionbarpulltorefresh.library.sdk.Compat; class AnimationRunnable implements Runnable { static interface AnimatorUpdateListener { /** * <p>Notifies the occurrence of another frame of the animation.</p> * * @param animation The animation which was repeated. */ void onAnimationUpdate(AnimationRunnable animation); } public static final int INFINITE = -1; private final View mView; private boolean mStarted; private int mDuration; private long mStartTime; private Interpolator mInterpolator; private int mRunCount; private int mRepeatCount; private float mAnimationValue; private AnimatorUpdateListener mUpdateListener; public AnimationRunnable(View view) { mView = view; } public void setDuration(int duration) { mDuration = duration; } public void setInterpolator(Interpolator interpolator) { mInterpolator = interpolator; } public void setRepeatCount(int repeatCount) { mRepeatCount = repeatCount; } public void setUpdateListener(AnimatorUpdateListener listener) { mUpdateListener = listener; } public void start() { if (mStarted) return; checkState(); mRunCount = 0; mStarted = true; mStartTime = AnimationUtils.currentAnimationTimeMillis(); Compat.postOnAnimation(mView, this); } private void restart() { mStartTime = AnimationUtils.currentAnimationTimeMillis(); Compat.postOnAnimation(mView, this); } public void cancel() { mStarted = false; mView.removeCallbacks(this); } public boolean isStarted() { return mStarted; } public float getAnimatedValue() { return mAnimationValue; } @Override public final void run() { if (!mStarted || mUpdateListener == null) return; final long timeElapsed = AnimationUtils.currentAnimationTimeMillis() - mStartTime; mAnimationValue = mInterpolator.getInterpolation(timeElapsed / (float) mDuration); mUpdateListener.onAnimationUpdate(this); if (timeElapsed < mDuration) { Compat.postOnAnimation(mView, this); } else { if (++mRunCount < mRepeatCount || mRepeatCount == INFINITE) { restart(); } } } private void checkState() { if (mInterpolator == null) { mInterpolator = new LinearInterpolator(); } if (mDuration == 0) { mDuration = mView.getResources().getInteger(android.R.integer.config_shortAnimTime); } } }