| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.animation; |
| |
| /** |
| * This class holds a time/value pair for an animation. The Keyframe class is used |
| * by {@link ValueAnimator} to define the values that the animation target will have over the course |
| * of the animation. As the time proceeds from one keyframe to the other, the value of the |
| * target object will animate between the value at the previous keyframe and the value at the |
| * next keyframe. Each keyframe also holds an optional {@link TimeInterpolator} |
| * object, which defines the time interpolation over the intervalue preceding the keyframe. |
| * |
| * <p>The Keyframe class itself is abstract. The type-specific factory methods will return |
| * a subclass of Keyframe specific to the type of value being stored. This is done to improve |
| * performance when dealing with the most common cases (e.g., <code>float</code> and |
| * <code>int</code> values). Other types will fall into a more general Keyframe class that |
| * treats its values as Objects. Unless your animation requires dealing with a custom type |
| * or a data structure that needs to be animated directly (and evaluated using an implementation |
| * of {@link TypeEvaluator}), you should stick to using float and int as animations using those |
| * types have lower runtime overhead than other types.</p> |
| */ |
| public abstract class Keyframe implements Cloneable { |
| /** |
| * Flag to indicate whether this keyframe has a valid value. This flag is used when an |
| * animation first starts, to populate placeholder keyframes with real values derived |
| * from the target object. |
| */ |
| boolean mHasValue; |
| |
| /** |
| * Flag to indicate whether the value in the keyframe was read from the target object or not. |
| * If so, its value will be recalculated if target changes. |
| */ |
| boolean mValueWasSetOnStart; |
| |
| |
| /** |
| * The time at which mValue will hold true. |
| */ |
| float mFraction; |
| |
| /** |
| * The type of the value in this Keyframe. This type is determined at construction time, |
| * based on the type of the <code>value</code> object passed into the constructor. |
| */ |
| Class mValueType; |
| |
| /** |
| * The optional time interpolator for the interval preceding this keyframe. A null interpolator |
| * (the default) results in linear interpolation over the interval. |
| */ |
| private TimeInterpolator mInterpolator = null; |
| |
| |
| |
| /** |
| * Constructs a Keyframe object with the given time and value. The time defines the |
| * time, as a proportion of an overall animation's duration, at which the value will hold true |
| * for the animation. The value for the animation between keyframes will be calculated as |
| * an interpolation between the values at those keyframes. |
| * |
| * @param fraction The time, expressed as a value between 0 and 1, representing the fraction |
| * of time elapsed of the overall animation duration. |
| * @param value The value that the object will animate to as the animation time approaches |
| * the time in this keyframe, and the value animated from as the time passes the time in |
| * this keyframe. |
| */ |
| public static Keyframe ofInt(float fraction, int value) { |
| return new IntKeyframe(fraction, value); |
| } |
| |
| /** |
| * Constructs a Keyframe object with the given time. The value at this time will be derived |
| * from the target object when the animation first starts (note that this implies that keyframes |
| * with no initial value must be used as part of an {@link ObjectAnimator}). |
| * The time defines the |
| * time, as a proportion of an overall animation's duration, at which the value will hold true |
| * for the animation. The value for the animation between keyframes will be calculated as |
| * an interpolation between the values at those keyframes. |
| * |
| * @param fraction The time, expressed as a value between 0 and 1, representing the fraction |
| * of time elapsed of the overall animation duration. |
| */ |
| public static Keyframe ofInt(float fraction) { |
| return new IntKeyframe(fraction); |
| } |
| |
| /** |
| * Constructs a Keyframe object with the given time and value. The time defines the |
| * time, as a proportion of an overall animation's duration, at which the value will hold true |
| * for the animation. The value for the animation between keyframes will be calculated as |
| * an interpolation between the values at those keyframes. |
| * |
| * @param fraction The time, expressed as a value between 0 and 1, representing the fraction |
| * of time elapsed of the overall animation duration. |
| * @param value The value that the object will animate to as the animation time approaches |
| * the time in this keyframe, and the value animated from as the time passes the time in |
| * this keyframe. |
| */ |
| public static Keyframe ofFloat(float fraction, float value) { |
| return new FloatKeyframe(fraction, value); |
| } |
| |
| /** |
| * Constructs a Keyframe object with the given time. The value at this time will be derived |
| * from the target object when the animation first starts (note that this implies that keyframes |
| * with no initial value must be used as part of an {@link ObjectAnimator}). |
| * The time defines the |
| * time, as a proportion of an overall animation's duration, at which the value will hold true |
| * for the animation. The value for the animation between keyframes will be calculated as |
| * an interpolation between the values at those keyframes. |
| * |
| * @param fraction The time, expressed as a value between 0 and 1, representing the fraction |
| * of time elapsed of the overall animation duration. |
| */ |
| public static Keyframe ofFloat(float fraction) { |
| return new FloatKeyframe(fraction); |
| } |
| |
| /** |
| * Constructs a Keyframe object with the given time and value. The time defines the |
| * time, as a proportion of an overall animation's duration, at which the value will hold true |
| * for the animation. The value for the animation between keyframes will be calculated as |
| * an interpolation between the values at those keyframes. |
| * |
| * @param fraction The time, expressed as a value between 0 and 1, representing the fraction |
| * of time elapsed of the overall animation duration. |
| * @param value The value that the object will animate to as the animation time approaches |
| * the time in this keyframe, and the value animated from as the time passes the time in |
| * this keyframe. |
| */ |
| public static Keyframe ofObject(float fraction, Object value) { |
| return new ObjectKeyframe(fraction, value); |
| } |
| |
| /** |
| * Constructs a Keyframe object with the given time. The value at this time will be derived |
| * from the target object when the animation first starts (note that this implies that keyframes |
| * with no initial value must be used as part of an {@link ObjectAnimator}). |
| * The time defines the |
| * time, as a proportion of an overall animation's duration, at which the value will hold true |
| * for the animation. The value for the animation between keyframes will be calculated as |
| * an interpolation between the values at those keyframes. |
| * |
| * @param fraction The time, expressed as a value between 0 and 1, representing the fraction |
| * of time elapsed of the overall animation duration. |
| */ |
| public static Keyframe ofObject(float fraction) { |
| return new ObjectKeyframe(fraction, null); |
| } |
| |
| /** |
| * Indicates whether this keyframe has a valid value. This method is called internally when |
| * an {@link ObjectAnimator} first starts; keyframes without values are assigned values at |
| * that time by deriving the value for the property from the target object. |
| * |
| * @return boolean Whether this object has a value assigned. |
| */ |
| public boolean hasValue() { |
| return mHasValue; |
| } |
| |
| /** |
| * If the Keyframe's value was acquired from the target object, this flag should be set so that, |
| * if target changes, value will be reset. |
| * |
| * @return boolean Whether this Keyframe's value was retieved from the target object or not. |
| */ |
| boolean valueWasSetOnStart() { |
| return mValueWasSetOnStart; |
| } |
| |
| void setValueWasSetOnStart(boolean valueWasSetOnStart) { |
| mValueWasSetOnStart = valueWasSetOnStart; |
| } |
| |
| /** |
| * Gets the value for this Keyframe. |
| * |
| * @return The value for this Keyframe. |
| */ |
| public abstract Object getValue(); |
| |
| /** |
| * Sets the value for this Keyframe. |
| * |
| * @param value value for this Keyframe. |
| */ |
| public abstract void setValue(Object value); |
| |
| /** |
| * Gets the time for this keyframe, as a fraction of the overall animation duration. |
| * |
| * @return The time associated with this keyframe, as a fraction of the overall animation |
| * duration. This should be a value between 0 and 1. |
| */ |
| public float getFraction() { |
| return mFraction; |
| } |
| |
| /** |
| * Sets the time for this keyframe, as a fraction of the overall animation duration. |
| * |
| * @param fraction time associated with this keyframe, as a fraction of the overall animation |
| * duration. This should be a value between 0 and 1. |
| */ |
| public void setFraction(float fraction) { |
| mFraction = fraction; |
| } |
| |
| /** |
| * Gets the optional interpolator for this Keyframe. A value of <code>null</code> indicates |
| * that there is no interpolation, which is the same as linear interpolation. |
| * |
| * @return The optional interpolator for this Keyframe. |
| */ |
| public TimeInterpolator getInterpolator() { |
| return mInterpolator; |
| } |
| |
| /** |
| * Sets the optional interpolator for this Keyframe. A value of <code>null</code> indicates |
| * that there is no interpolation, which is the same as linear interpolation. |
| * |
| * @return The optional interpolator for this Keyframe. |
| */ |
| public void setInterpolator(TimeInterpolator interpolator) { |
| mInterpolator = interpolator; |
| } |
| |
| /** |
| * Gets the type of keyframe. This information is used by ValueAnimator to determine the type of |
| * {@link TypeEvaluator} to use when calculating values between keyframes. The type is based |
| * on the type of Keyframe created. |
| * |
| * @return The type of the value stored in the Keyframe. |
| */ |
| public Class getType() { |
| return mValueType; |
| } |
| |
| @Override |
| public abstract Keyframe clone(); |
| |
| /** |
| * This internal subclass is used for all types which are not int or float. |
| */ |
| static class ObjectKeyframe extends Keyframe { |
| |
| /** |
| * The value of the animation at the time mFraction. |
| */ |
| Object mValue; |
| |
| ObjectKeyframe(float fraction, Object value) { |
| mFraction = fraction; |
| mValue = value; |
| mHasValue = (value != null); |
| mValueType = mHasValue ? value.getClass() : Object.class; |
| } |
| |
| public Object getValue() { |
| return mValue; |
| } |
| |
| public void setValue(Object value) { |
| mValue = value; |
| mHasValue = (value != null); |
| } |
| |
| @Override |
| public ObjectKeyframe clone() { |
| ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), hasValue() ? mValue : null); |
| kfClone.mValueWasSetOnStart = mValueWasSetOnStart; |
| kfClone.setInterpolator(getInterpolator()); |
| return kfClone; |
| } |
| } |
| |
| /** |
| * Internal subclass used when the keyframe value is of type int. |
| */ |
| static class IntKeyframe extends Keyframe { |
| |
| /** |
| * The value of the animation at the time mFraction. |
| */ |
| int mValue; |
| |
| IntKeyframe(float fraction, int value) { |
| mFraction = fraction; |
| mValue = value; |
| mValueType = int.class; |
| mHasValue = true; |
| } |
| |
| IntKeyframe(float fraction) { |
| mFraction = fraction; |
| mValueType = int.class; |
| } |
| |
| public int getIntValue() { |
| return mValue; |
| } |
| |
| public Object getValue() { |
| return mValue; |
| } |
| |
| public void setValue(Object value) { |
| if (value != null && value.getClass() == Integer.class) { |
| mValue = ((Integer)value).intValue(); |
| mHasValue = true; |
| } |
| } |
| |
| @Override |
| public IntKeyframe clone() { |
| IntKeyframe kfClone = mHasValue ? |
| new IntKeyframe(getFraction(), mValue) : |
| new IntKeyframe(getFraction()); |
| kfClone.setInterpolator(getInterpolator()); |
| kfClone.mValueWasSetOnStart = mValueWasSetOnStart; |
| return kfClone; |
| } |
| } |
| |
| /** |
| * Internal subclass used when the keyframe value is of type float. |
| */ |
| static class FloatKeyframe extends Keyframe { |
| /** |
| * The value of the animation at the time mFraction. |
| */ |
| float mValue; |
| |
| FloatKeyframe(float fraction, float value) { |
| mFraction = fraction; |
| mValue = value; |
| mValueType = float.class; |
| mHasValue = true; |
| } |
| |
| FloatKeyframe(float fraction) { |
| mFraction = fraction; |
| mValueType = float.class; |
| } |
| |
| public float getFloatValue() { |
| return mValue; |
| } |
| |
| public Object getValue() { |
| return mValue; |
| } |
| |
| public void setValue(Object value) { |
| if (value != null && value.getClass() == Float.class) { |
| mValue = ((Float)value).floatValue(); |
| mHasValue = true; |
| } |
| } |
| |
| @Override |
| public FloatKeyframe clone() { |
| FloatKeyframe kfClone = mHasValue ? |
| new FloatKeyframe(getFraction(), mValue) : |
| new FloatKeyframe(getFraction()); |
| kfClone.setInterpolator(getInterpolator()); |
| kfClone.mValueWasSetOnStart = mValueWasSetOnStart; |
| return kfClone; |
| } |
| } |
| } |