/**
   * Gets the animated value, given the elapsed fraction of the animation (interpolated by the
   * animation's interpolator) and the evaluator used to calculate in-between values. This function
   * maps the input fraction to the appropriate keyframe interval and a fraction between them and
   * returns the interpolated value. Note that the input fraction may fall outside the [0-1] bounds,
   * if the animation's interpolator made that happen (e.g., a spring interpolation that might send
   * the fraction past 1.0). We handle this situation by just using the two keyframes at the
   * appropriate end when the value is outside those bounds.
   *
   * @param fraction The elapsed fraction of the animation
   * @return The animated value.
   */
  public Object getValue(float fraction) {

    // Special-case optimization for the common case of only two keyframes
    if (mNumKeyframes == 2) {
      if (mInterpolator != null) {
        fraction = mInterpolator.getInterpolation(fraction);
      }
      return mEvaluator.evaluate(fraction, mFirstKeyframe.getValue(), mLastKeyframe.getValue());
    }
    if (fraction <= 0f) {
      final Keyframe nextKeyframe = mKeyframes.get(1);
      final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
      if (interpolator != null) {
        fraction = interpolator.getInterpolation(fraction);
      }
      final float prevFraction = mFirstKeyframe.getFraction();
      float intervalFraction =
          (fraction - prevFraction) / (nextKeyframe.getFraction() - prevFraction);
      return mEvaluator.evaluate(
          intervalFraction, mFirstKeyframe.getValue(), nextKeyframe.getValue());
    } else if (fraction >= 1f) {
      final Keyframe prevKeyframe = mKeyframes.get(mNumKeyframes - 2);
      final TimeInterpolator interpolator = mLastKeyframe.getInterpolator();
      if (interpolator != null) {
        fraction = interpolator.getInterpolation(fraction);
      }
      final float prevFraction = prevKeyframe.getFraction();
      float intervalFraction =
          (fraction - prevFraction) / (mLastKeyframe.getFraction() - prevFraction);
      return mEvaluator.evaluate(
          intervalFraction, prevKeyframe.getValue(), mLastKeyframe.getValue());
    }
    Keyframe prevKeyframe = mFirstKeyframe;
    for (int i = 1; i < mNumKeyframes; ++i) {
      Keyframe nextKeyframe = mKeyframes.get(i);
      if (fraction < nextKeyframe.getFraction()) {
        final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
        if (interpolator != null) {
          fraction = interpolator.getInterpolation(fraction);
        }
        final float prevFraction = prevKeyframe.getFraction();
        float intervalFraction =
            (fraction - prevFraction) / (nextKeyframe.getFraction() - prevFraction);
        return mEvaluator.evaluate(
            intervalFraction, prevKeyframe.getValue(), nextKeyframe.getValue());
      }
      prevKeyframe = nextKeyframe;
    }
    // shouldn't reach here
    return mLastKeyframe.getValue();
  }
 public KeyframeSet(Keyframe... keyframes) {
   mNumKeyframes = keyframes.length;
   mKeyframes = new ArrayList<Keyframe>();
   mKeyframes.addAll(Arrays.asList(keyframes));
   mFirstKeyframe = mKeyframes.get(0);
   mLastKeyframe = mKeyframes.get(mNumKeyframes - 1);
   mInterpolator = mLastKeyframe.getInterpolator();
 }