/* * 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. * *
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., float
and
* int
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.
value
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 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 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 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 null
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 null
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;
}
}
}