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