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      * 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