Home | History | Annotate | Download | only in animation
      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