1 /*
2  * Copyright (C) 2010 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 
17 package android.animation;
18 
19 /**
20  * This class holds a time/value pair for an animation. The Keyframe class is used
21  * by {@link ValueAnimator} to define the values that the animation target will have over the course
22  * of the animation. As the time proceeds from one keyframe to the other, the value of the
23  * target object will animate between the value at the previous keyframe and the value at the
24  * next keyframe. Each keyframe also holds an optional {@link TimeInterpolator}
25  * object, which defines the time interpolation over the intervalue preceding the keyframe.
26  *
27  * <p>The Keyframe class itself is abstract. The type-specific factory methods will return
28  * a subclass of Keyframe specific to the type of value being stored. This is done to improve
29  * performance when dealing with the most common cases (e.g., <code>float</code> and
30  * <code>int</code> values). Other types will fall into a more general Keyframe class that
31  * treats its values as Objects. Unless your animation requires dealing with a custom type
32  * or a data structure that needs to be animated directly (and evaluated using an implementation
33  * of {@link TypeEvaluator}), you should stick to using float and int as animations using those
34  * types have lower runtime overhead than other types.</p>
35  */
36 public abstract class Keyframe implements Cloneable {
37     /**
38      * Flag to indicate whether this keyframe has a valid value. This flag is used when an
39      * animation first starts, to populate placeholder keyframes with real values derived
40      * from the target object.
41      */
42     boolean mHasValue;
43 
44     /**
45      * Flag to indicate whether the value in the keyframe was read from the target object or not.
46      * If so, its value will be recalculated if target changes.
47      */
48     boolean mValueWasSetOnStart;
49 
50 
51     /**
52      * The time at which mValue will hold true.
53      */
54     float mFraction;
55 
56     /**
57      * The type of the value in this Keyframe. This type is determined at construction time,
58      * based on the type of the <code>value</code> object passed into the constructor.
59      */
60     Class mValueType;
61 
62     /**
63      * The optional time interpolator for the interval preceding this keyframe. A null interpolator
64      * (the default) results in linear interpolation over the interval.
65      */
66     private TimeInterpolator mInterpolator = null;
67 
68 
69 
70     /**
71      * Constructs a Keyframe object with the given time and value. The time defines the
72      * time, as a proportion of an overall animation's duration, at which the value will hold true
73      * for the animation. The value for the animation between keyframes will be calculated as
74      * an interpolation between the values at those keyframes.
75      *
76      * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
77      * of time elapsed of the overall animation duration.
78      * @param value The value that the object will animate to as the animation time approaches
79      * the time in this keyframe, and the the value animated from as the time passes the time in
80      * this keyframe.
81      */
ofInt(float fraction, int value)82     public static Keyframe ofInt(float fraction, int value) {
83         return new IntKeyframe(fraction, value);
84     }
85 
86     /**
87      * Constructs a Keyframe object with the given time. The value at this time will be derived
88      * from the target object when the animation first starts (note that this implies that keyframes
89      * with no initial value must be used as part of an {@link ObjectAnimator}).
90      * The time defines the
91      * time, as a proportion of an overall animation's duration, at which the value will hold true
92      * for the animation. The value for the animation between keyframes will be calculated as
93      * an interpolation between the values at those keyframes.
94      *
95      * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
96      * of time elapsed of the overall animation duration.
97      */
ofInt(float fraction)98     public static Keyframe ofInt(float fraction) {
99         return new IntKeyframe(fraction);
100     }
101 
102     /**
103      * Constructs a Keyframe object with the given time and value. The time defines the
104      * time, as a proportion of an overall animation's duration, at which the value will hold true
105      * for the animation. The value for the animation between keyframes will be calculated as
106      * an interpolation between the values at those keyframes.
107      *
108      * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
109      * of time elapsed of the overall animation duration.
110      * @param value The value that the object will animate to as the animation time approaches
111      * the time in this keyframe, and the the value animated from as the time passes the time in
112      * this keyframe.
113      */
ofFloat(float fraction, float value)114     public static Keyframe ofFloat(float fraction, float value) {
115         return new FloatKeyframe(fraction, value);
116     }
117 
118     /**
119      * Constructs a Keyframe object with the given time. The value at this time will be derived
120      * from the target object when the animation first starts (note that this implies that keyframes
121      * with no initial value must be used as part of an {@link ObjectAnimator}).
122      * The time defines the
123      * time, as a proportion of an overall animation's duration, at which the value will hold true
124      * for the animation. The value for the animation between keyframes will be calculated as
125      * an interpolation between the values at those keyframes.
126      *
127      * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
128      * of time elapsed of the overall animation duration.
129      */
ofFloat(float fraction)130     public static Keyframe ofFloat(float fraction) {
131         return new FloatKeyframe(fraction);
132     }
133 
134     /**
135      * Constructs a Keyframe object with the given time and value. The time defines the
136      * time, as a proportion of an overall animation's duration, at which the value will hold true
137      * for the animation. The value for the animation between keyframes will be calculated as
138      * an interpolation between the values at those keyframes.
139      *
140      * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
141      * of time elapsed of the overall animation duration.
142      * @param value The value that the object will animate to as the animation time approaches
143      * the time in this keyframe, and the the value animated from as the time passes the time in
144      * this keyframe.
145      */
ofObject(float fraction, Object value)146     public static Keyframe ofObject(float fraction, Object value) {
147         return new ObjectKeyframe(fraction, value);
148     }
149 
150     /**
151      * Constructs a Keyframe object with the given time. The value at this time will be derived
152      * from the target object when the animation first starts (note that this implies that keyframes
153      * with no initial value must be used as part of an {@link ObjectAnimator}).
154      * The time defines the
155      * time, as a proportion of an overall animation's duration, at which the value will hold true
156      * for the animation. The value for the animation between keyframes will be calculated as
157      * an interpolation between the values at those keyframes.
158      *
159      * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
160      * of time elapsed of the overall animation duration.
161      */
ofObject(float fraction)162     public static Keyframe ofObject(float fraction) {
163         return new ObjectKeyframe(fraction, null);
164     }
165 
166     /**
167      * Indicates whether this keyframe has a valid value. This method is called internally when
168      * an {@link ObjectAnimator} first starts; keyframes without values are assigned values at
169      * that time by deriving the value for the property from the target object.
170      *
171      * @return boolean Whether this object has a value assigned.
172      */
hasValue()173     public boolean hasValue() {
174         return mHasValue;
175     }
176 
177     /**
178      * If the Keyframe's value was acquired from the target object, this flag should be set so that,
179      * if target changes, value will be reset.
180      *
181      * @return boolean Whether this Keyframe's value was retieved from the target object or not.
182      */
valueWasSetOnStart()183     boolean valueWasSetOnStart() {
184         return mValueWasSetOnStart;
185     }
186 
setValueWasSetOnStart(boolean valueWasSetOnStart)187     void setValueWasSetOnStart(boolean valueWasSetOnStart) {
188         mValueWasSetOnStart = valueWasSetOnStart;
189     }
190 
191     /**
192      * Gets the value for this Keyframe.
193      *
194      * @return The value for this Keyframe.
195      */
getValue()196     public abstract Object getValue();
197 
198     /**
199      * Sets the value for this Keyframe.
200      *
201      * @param value value for this Keyframe.
202      */
setValue(Object value)203     public abstract void setValue(Object value);
204 
205     /**
206      * Gets the time for this keyframe, as a fraction of the overall animation duration.
207      *
208      * @return The time associated with this keyframe, as a fraction of the overall animation
209      * duration. This should be a value between 0 and 1.
210      */
getFraction()211     public float getFraction() {
212         return mFraction;
213     }
214 
215     /**
216      * Sets the time for this keyframe, as a fraction of the overall animation duration.
217      *
218      * @param fraction time associated with this keyframe, as a fraction of the overall animation
219      * duration. This should be a value between 0 and 1.
220      */
setFraction(float fraction)221     public void setFraction(float fraction) {
222         mFraction = fraction;
223     }
224 
225     /**
226      * Gets the optional interpolator for this Keyframe. A value of <code>null</code> indicates
227      * that there is no interpolation, which is the same as linear interpolation.
228      *
229      * @return The optional interpolator for this Keyframe.
230      */
getInterpolator()231     public TimeInterpolator getInterpolator() {
232         return mInterpolator;
233     }
234 
235     /**
236      * Sets the optional interpolator for this Keyframe. A value of <code>null</code> indicates
237      * that there is no interpolation, which is the same as linear interpolation.
238      *
239      * @return The optional interpolator for this Keyframe.
240      */
setInterpolator(TimeInterpolator interpolator)241     public void setInterpolator(TimeInterpolator interpolator) {
242         mInterpolator = interpolator;
243     }
244 
245     /**
246      * Gets the type of keyframe. This information is used by ValueAnimator to determine the type of
247      * {@link TypeEvaluator} to use when calculating values between keyframes. The type is based
248      * on the type of Keyframe created.
249      *
250      * @return The type of the value stored in the Keyframe.
251      */
getType()252     public Class getType() {
253         return mValueType;
254     }
255 
256     @Override
clone()257     public abstract Keyframe clone();
258 
259     /**
260      * This internal subclass is used for all types which are not int or float.
261      */
262     static class ObjectKeyframe extends Keyframe {
263 
264         /**
265          * The value of the animation at the time mFraction.
266          */
267         Object mValue;
268 
ObjectKeyframe(float fraction, Object value)269         ObjectKeyframe(float fraction, Object value) {
270             mFraction = fraction;
271             mValue = value;
272             mHasValue = (value != null);
273             mValueType = mHasValue ? value.getClass() : Object.class;
274         }
275 
getValue()276         public Object getValue() {
277             return mValue;
278         }
279 
setValue(Object value)280         public void setValue(Object value) {
281             mValue = value;
282             mHasValue = (value != null);
283         }
284 
285         @Override
clone()286         public ObjectKeyframe clone() {
287             ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), hasValue() ? mValue : null);
288             kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
289             kfClone.setInterpolator(getInterpolator());
290             return kfClone;
291         }
292     }
293 
294     /**
295      * Internal subclass used when the keyframe value is of type int.
296      */
297     static class IntKeyframe extends Keyframe {
298 
299         /**
300          * The value of the animation at the time mFraction.
301          */
302         int mValue;
303 
IntKeyframe(float fraction, int value)304         IntKeyframe(float fraction, int value) {
305             mFraction = fraction;
306             mValue = value;
307             mValueType = int.class;
308             mHasValue = true;
309         }
310 
IntKeyframe(float fraction)311         IntKeyframe(float fraction) {
312             mFraction = fraction;
313             mValueType = int.class;
314         }
315 
getIntValue()316         public int getIntValue() {
317             return mValue;
318         }
319 
getValue()320         public Object getValue() {
321             return mValue;
322         }
323 
setValue(Object value)324         public void setValue(Object value) {
325             if (value != null && value.getClass() == Integer.class) {
326                 mValue = ((Integer)value).intValue();
327                 mHasValue = true;
328             }
329         }
330 
331         @Override
clone()332         public IntKeyframe clone() {
333             IntKeyframe kfClone = mHasValue ?
334                     new IntKeyframe(getFraction(), mValue) :
335                     new IntKeyframe(getFraction());
336             kfClone.setInterpolator(getInterpolator());
337             kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
338             return kfClone;
339         }
340     }
341 
342     /**
343      * Internal subclass used when the keyframe value is of type float.
344      */
345     static class FloatKeyframe extends Keyframe {
346         /**
347          * The value of the animation at the time mFraction.
348          */
349         float mValue;
350 
FloatKeyframe(float fraction, float value)351         FloatKeyframe(float fraction, float value) {
352             mFraction = fraction;
353             mValue = value;
354             mValueType = float.class;
355             mHasValue = true;
356         }
357 
FloatKeyframe(float fraction)358         FloatKeyframe(float fraction) {
359             mFraction = fraction;
360             mValueType = float.class;
361         }
362 
getFloatValue()363         public float getFloatValue() {
364             return mValue;
365         }
366 
getValue()367         public Object getValue() {
368             return mValue;
369         }
370 
setValue(Object value)371         public void setValue(Object value) {
372             if (value != null && value.getClass() == Float.class) {
373                 mValue = ((Float)value).floatValue();
374                 mHasValue = true;
375             }
376         }
377 
378         @Override
clone()379         public FloatKeyframe clone() {
380             FloatKeyframe kfClone = mHasValue ?
381                     new FloatKeyframe(getFraction(), mValue) :
382                     new FloatKeyframe(getFraction());
383             kfClone.setInterpolator(getInterpolator());
384             kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
385             return kfClone;
386         }
387     }
388 }
389