blob: 5483c49aef54e1e6862959e9a97e0dc03bead36e [file] [log] [blame]
Chet Haase3dd207a2010-07-20 14:00:01 -07001/*
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
17package android.animation;
18
Chet Haase3dd207a2010-07-20 14:00:01 -070019/**
Chet Haase3b69b6f2010-07-29 09:09:05 -070020 * This class holds a time/value pair for an animation. The Keyframe class is used
Chet Haasea18a86b2010-09-07 13:20:00 -070021 * by {@link ValueAnimator} to define the values that the animation target will have over the course
Chet Haase3dd207a2010-07-20 14:00:01 -070022 * 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
Chet Haasee0ee2e92010-10-07 09:06:18 -070024 * next keyframe. Each keyframe also holds an optional {@link TimeInterpolator}
Chet Haase3dd207a2010-07-20 14:00:01 -070025 * object, which defines the time interpolation over the intervalue preceding the keyframe.
Chet Haase7c608f22010-10-22 17:54:04 -070026 *
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>
Chet Haase3dd207a2010-07-20 14:00:01 -070035 */
Chet Haase7c608f22010-10-22 17:54:04 -070036public abstract class Keyframe implements Cloneable {
Chet Haase3dd207a2010-07-20 14:00:01 -070037 /**
Yigit Boyar8619f482014-07-15 17:28:07 -070038 * 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 /**
Chet Haase3dd207a2010-07-20 14:00:01 -070052 * The time at which mValue will hold true.
53 */
Chet Haase7c608f22010-10-22 17:54:04 -070054 float mFraction;
Chet Haase3dd207a2010-07-20 14:00:01 -070055
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 */
Chet Haase7c608f22010-10-22 17:54:04 -070060 Class mValueType;
Chet Haase3dd207a2010-07-20 14:00:01 -070061
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 */
Chet Haasee0ee2e92010-10-07 09:06:18 -070066 private TimeInterpolator mInterpolator = null;
Chet Haase3dd207a2010-07-20 14:00:01 -070067
Yigit Boyar8619f482014-07-15 17:28:07 -070068
Chet Haase7c608f22010-10-22 17:54:04 -070069
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.
Chet Haase3dd207a2010-07-20 14:00:01 -070075 *
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.
Chet Haase3dd207a2010-07-20 14:00:01 -070081 */
Chet Haase7c608f22010-10-22 17:54:04 -070082 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 */
98 public static Keyframe ofInt(float fraction) {
99 return new IntKeyframe(fraction);
Chet Haase3dd207a2010-07-20 14:00:01 -0700100 }
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 */
Chet Haase7c608f22010-10-22 17:54:04 -0700114 public static Keyframe ofFloat(float fraction, float value) {
115 return new FloatKeyframe(fraction, value);
Chet Haase21cd1382010-09-01 17:42:29 -0700116 }
117
118 /**
Chet Haase7c608f22010-10-22 17:54:04 -0700119 * 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 */
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
Chet Haase21cd1382010-09-01 17:42:29 -0700136 * 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 */
Chet Haase7c608f22010-10-22 17:54:04 -0700146 public static Keyframe ofObject(float fraction, Object value) {
147 return new ObjectKeyframe(fraction, value);
Chet Haase21cd1382010-09-01 17:42:29 -0700148 }
149
150 /**
Chet Haase7c608f22010-10-22 17:54:04 -0700151 * 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
Chet Haase21cd1382010-09-01 17:42:29 -0700155 * 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.
Chet Haase21cd1382010-09-01 17:42:29 -0700161 */
Chet Haase7c608f22010-10-22 17:54:04 -0700162 public static Keyframe ofObject(float fraction) {
163 return new ObjectKeyframe(fraction, null);
Chet Haase21cd1382010-09-01 17:42:29 -0700164 }
165
166 /**
Chet Haase7c608f22010-10-22 17:54:04 -0700167 * 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.
Chet Haase21cd1382010-09-01 17:42:29 -0700170 *
Chet Haase7c608f22010-10-22 17:54:04 -0700171 * @return boolean Whether this object has a value assigned.
Chet Haase21cd1382010-09-01 17:42:29 -0700172 */
Chet Haase7c608f22010-10-22 17:54:04 -0700173 public boolean hasValue() {
174 return mHasValue;
Chet Haase3dd207a2010-07-20 14:00:01 -0700175 }
176
177 /**
Yigit Boyar8619f482014-07-15 17:28:07 -0700178 * 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 */
183 boolean valueWasSetOnStart() {
184 return mValueWasSetOnStart;
185 }
186
187 void setValueWasSetOnStart(boolean valueWasSetOnStart) {
188 mValueWasSetOnStart = valueWasSetOnStart;
189 }
190
191 /**
Chet Haase3dd207a2010-07-20 14:00:01 -0700192 * Gets the value for this Keyframe.
193 *
194 * @return The value for this Keyframe.
195 */
Chet Haase7c608f22010-10-22 17:54:04 -0700196 public abstract Object getValue();
Chet Haase3dd207a2010-07-20 14:00:01 -0700197
198 /**
Chet Haasefe591562010-07-27 11:15:37 -0700199 * Sets the value for this Keyframe.
200 *
Chet Haase3b69b6f2010-07-29 09:09:05 -0700201 * @param value value for this Keyframe.
Chet Haasefe591562010-07-27 11:15:37 -0700202 */
Chet Haase7c608f22010-10-22 17:54:04 -0700203 public abstract void setValue(Object value);
Chet Haasefe591562010-07-27 11:15:37 -0700204
205 /**
Chet Haase3dd207a2010-07-20 14:00:01 -0700206 * 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 */
211 public float getFraction() {
212 return mFraction;
213 }
214
215 /**
Chet Haasefe591562010-07-27 11:15:37 -0700216 * Sets the time for this keyframe, as a fraction of the overall animation duration.
217 *
Chet Haase3b69b6f2010-07-29 09:09:05 -0700218 * @param fraction time associated with this keyframe, as a fraction of the overall animation
Chet Haasefe591562010-07-27 11:15:37 -0700219 * duration. This should be a value between 0 and 1.
220 */
221 public void setFraction(float fraction) {
222 mFraction = fraction;
223 }
224
225 /**
Chet Haase3dd207a2010-07-20 14:00:01 -0700226 * 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 */
Chet Haasee0ee2e92010-10-07 09:06:18 -0700231 public TimeInterpolator getInterpolator() {
Chet Haase3dd207a2010-07-20 14:00:01 -0700232 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 */
Chet Haasee0ee2e92010-10-07 09:06:18 -0700241 public void setInterpolator(TimeInterpolator interpolator) {
Chet Haase3dd207a2010-07-20 14:00:01 -0700242 mInterpolator = interpolator;
243 }
244
245 /**
Chet Haasea18a86b2010-09-07 13:20:00 -0700246 * Gets the type of keyframe. This information is used by ValueAnimator to determine the type of
Chet Haase3b69b6f2010-07-29 09:09:05 -0700247 * {@link TypeEvaluator} to use when calculating values between keyframes. The type is based
248 * on the type of Keyframe created.
Chet Haase3dd207a2010-07-20 14:00:01 -0700249 *
250 * @return The type of the value stored in the Keyframe.
251 */
252 public Class getType() {
253 return mValueType;
254 }
Chet Haase21cd1382010-09-01 17:42:29 -0700255
256 @Override
Chet Haase7c608f22010-10-22 17:54:04 -0700257 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
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
276 public Object getValue() {
277 return mValue;
278 }
279
280 public void setValue(Object value) {
281 mValue = value;
282 mHasValue = (value != null);
283 }
284
285 @Override
286 public ObjectKeyframe clone() {
Yigit Boyar8619f482014-07-15 17:28:07 -0700287 ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), hasValue() ? mValue : null);
288 kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
Chet Haase7c608f22010-10-22 17:54:04 -0700289 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
304 IntKeyframe(float fraction, int value) {
305 mFraction = fraction;
306 mValue = value;
307 mValueType = int.class;
308 mHasValue = true;
309 }
310
311 IntKeyframe(float fraction) {
312 mFraction = fraction;
313 mValueType = int.class;
314 }
315
316 public int getIntValue() {
317 return mValue;
318 }
319
320 public Object getValue() {
321 return mValue;
322 }
323
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
332 public IntKeyframe clone() {
Chet Haase00177e42012-09-10 13:42:07 -0700333 IntKeyframe kfClone = mHasValue ?
334 new IntKeyframe(getFraction(), mValue) :
335 new IntKeyframe(getFraction());
Chet Haase7c608f22010-10-22 17:54:04 -0700336 kfClone.setInterpolator(getInterpolator());
Yigit Boyar8619f482014-07-15 17:28:07 -0700337 kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
Chet Haase7c608f22010-10-22 17:54:04 -0700338 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
351 FloatKeyframe(float fraction, float value) {
352 mFraction = fraction;
353 mValue = value;
354 mValueType = float.class;
355 mHasValue = true;
356 }
357
358 FloatKeyframe(float fraction) {
359 mFraction = fraction;
360 mValueType = float.class;
361 }
362
363 public float getFloatValue() {
364 return mValue;
365 }
366
367 public Object getValue() {
368 return mValue;
369 }
370
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
379 public FloatKeyframe clone() {
Chet Haase00177e42012-09-10 13:42:07 -0700380 FloatKeyframe kfClone = mHasValue ?
381 new FloatKeyframe(getFraction(), mValue) :
382 new FloatKeyframe(getFraction());
Chet Haase7c608f22010-10-22 17:54:04 -0700383 kfClone.setInterpolator(getInterpolator());
Yigit Boyar8619f482014-07-15 17:28:07 -0700384 kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
Chet Haase7c608f22010-10-22 17:54:04 -0700385 return kfClone;
386 }
Chet Haase21cd1382010-09-01 17:42:29 -0700387 }
Chet Haase3dd207a2010-07-20 14:00:01 -0700388}