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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 183 boolean valueWasSetOnStart() { 184 return mValueWasSetOnStart; 185 } 186 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 */ 196 public abstract Object getValue(); 197 198 /** 199 * Sets the value for this Keyframe. 200 * 201 * @param value value for this Keyframe. 202 */ 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 */ 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 */ 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 */ 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 */ 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 */ 252 public Class getType() { 253 return mValueType; 254 } 255 256 @Override 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 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() { 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 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() { 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 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() { 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