ValueAnimatorCompatImplEclairMr1.java revision 631f64ec9c6255f38a7f746d7949b6a537c1180f
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        if (mListener != null) {
63            mListener.onAnimationStart();
64        }
65
66        sHandler.postDelayed(mRunnable, HANDLER_DELAY);
67    }
68
69    @Override
70    public boolean isRunning() {
71        return mIsRunning;
72    }
73
74    @Override
75    public void setInterpolator(Interpolator interpolator) {
76        mInterpolator = interpolator;
77    }
78
79    @Override
80    public void setListener(AnimatorListenerProxy listener) {
81        mListener = listener;
82    }
83
84    @Override
85    public void setUpdateListener(AnimatorUpdateListenerProxy updateListener) {
86        mUpdateListener = updateListener;
87    }
88
89    @Override
90    public void setIntValues(int from, int to) {
91        mIntValues[0] = from;
92        mIntValues[1] = to;
93    }
94
95    @Override
96    public int getAnimatedIntValue() {
97        return AnimationUtils.lerp(mIntValues[0], mIntValues[1], getAnimatedFraction());
98    }
99
100    @Override
101    public void setFloatValues(float from, float to) {
102        mFloatValues[0] = from;
103        mFloatValues[1] = to;
104    }
105
106    @Override
107    public float getAnimatedFloatValue() {
108        return AnimationUtils.lerp(mFloatValues[0], mFloatValues[1], getAnimatedFraction());
109    }
110
111    @Override
112    public void setDuration(int duration) {
113        mDuration = duration;
114    }
115
116    @Override
117    public void cancel() {
118        mIsRunning = false;
119        sHandler.removeCallbacks(mRunnable);
120
121        if (mListener != null) {
122            mListener.onAnimationCancel();
123        }
124    }
125
126    @Override
127    public float getAnimatedFraction() {
128        return mAnimatedFraction;
129    }
130
131    @Override
132    public void end() {
133        if (mIsRunning) {
134            mIsRunning = false;
135            sHandler.removeCallbacks(mRunnable);
136
137            // Set our animated fraction to 1
138            mAnimatedFraction = 1f;
139
140            if (mUpdateListener != null) {
141                mUpdateListener.onAnimationUpdate();
142            }
143
144            if (mListener != null) {
145                mListener.onAnimationEnd();
146            }
147        }
148    }
149
150    private void update() {
151        if (mIsRunning) {
152            // Update the animated fraction
153            final long elapsed = SystemClock.uptimeMillis() - mStartTime;
154            final float linearFraction = elapsed / (float) mDuration;
155            mAnimatedFraction = mInterpolator != null
156                    ? mInterpolator.getInterpolation(linearFraction)
157                    : linearFraction;
158
159            // If we're running, dispatch tp the listener
160            if (mUpdateListener != null) {
161                mUpdateListener.onAnimationUpdate();
162            }
163
164            // Check to see if we've passed the animation duration
165            if (SystemClock.uptimeMillis() >= (mStartTime + mDuration)) {
166                mIsRunning = false;
167
168                if (mListener != null) {
169                    mListener.onAnimationEnd();
170                }
171            }
172        }
173
174        if (mIsRunning) {
175            // If we're still running, post another delayed runnable
176            sHandler.postDelayed(mRunnable, HANDLER_DELAY);
177        }
178    }
179
180    private final Runnable mRunnable = new Runnable() {
181        public void run() {
182            update();
183        }
184    };
185}
186