public ObjectAnimator getDisappearAnimator() {
    if (!this.mIsInitialized || !this.mDrawValuesReady) {
      Log.e(TAG, "RadialSelectorView was not ready for animation.");
      return null;
    }

    Keyframe kf0, kf1, kf2;
    float midwayPoint = 0.2f;
    int duration = 500;

    kf0 = Keyframe.ofFloat(0f, 1);
    kf1 = Keyframe.ofFloat(midwayPoint, this.mTransitionMidRadiusMultiplier);
    kf2 = Keyframe.ofFloat(1f, this.mTransitionEndRadiusMultiplier);
    PropertyValuesHolder radiusDisappear =
        PropertyValuesHolder.ofKeyframe("animationRadiusMultiplier", kf0, kf1, kf2);

    kf0 = Keyframe.ofFloat(0f, 1f);
    kf1 = Keyframe.ofFloat(1f, 0f);
    PropertyValuesHolder fadeOut = PropertyValuesHolder.ofKeyframe("alpha", kf0, kf1);

    ObjectAnimator disappearAnimator =
        ObjectAnimator.ofPropertyValuesHolder(this, radiusDisappear, fadeOut).setDuration(duration);
    disappearAnimator.addUpdateListener(this.mInvalidateUpdateListener);

    return disappearAnimator;
  }
  /** Render the animations for appearing and disappearing. */
  private void renderAnimations() {
    Keyframe kf0, kf1, kf2, kf3;
    float midwayPoint = 0.2f;
    int duration = 500;

    // Set up animator for disappearing.
    kf0 = Keyframe.ofFloat(0f, 1);
    kf1 = Keyframe.ofFloat(midwayPoint, mTransitionMidRadiusMultiplier);
    kf2 = Keyframe.ofFloat(1f, mTransitionEndRadiusMultiplier);
    PropertyValuesHolder radiusDisappear =
        PropertyValuesHolder.ofKeyframe("animationRadiusMultiplier", kf0, kf1, kf2);

    kf0 = Keyframe.ofFloat(0f, 1f);
    kf1 = Keyframe.ofFloat(1f, 0f);
    PropertyValuesHolder fadeOut = PropertyValuesHolder.ofKeyframe("alpha", kf0, kf1);

    mDisappearAnimator =
        ObjectAnimator.ofPropertyValuesHolder(
                AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : this,
                radiusDisappear,
                fadeOut)
            .setDuration(duration);
    mDisappearAnimator.addUpdateListener(mInvalidateUpdateListener);

    // Set up animator for reappearing.
    float delayMultiplier = 0.25f;
    float transitionDurationMultiplier = 1f;
    float totalDurationMultiplier = transitionDurationMultiplier + delayMultiplier;
    int totalDuration = (int) (duration * totalDurationMultiplier);
    float delayPoint = (delayMultiplier * duration) / totalDuration;
    midwayPoint = 1 - (midwayPoint * (1 - delayPoint));

    kf0 = Keyframe.ofFloat(0f, mTransitionEndRadiusMultiplier);
    kf1 = Keyframe.ofFloat(delayPoint, mTransitionEndRadiusMultiplier);
    kf2 = Keyframe.ofFloat(midwayPoint, mTransitionMidRadiusMultiplier);
    kf3 = Keyframe.ofFloat(1f, 1);
    PropertyValuesHolder radiusReappear =
        PropertyValuesHolder.ofKeyframe("animationRadiusMultiplier", kf0, kf1, kf2, kf3);

    kf0 = Keyframe.ofFloat(0f, 0f);
    kf1 = Keyframe.ofFloat(delayPoint, 0f);
    kf2 = Keyframe.ofFloat(1f, 1f);
    PropertyValuesHolder fadeIn = PropertyValuesHolder.ofKeyframe("alpha", kf0, kf1, kf2);

    mReappearAnimator =
        ObjectAnimator.ofPropertyValuesHolder(
                AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : this, radiusReappear, fadeIn)
            .setDuration(totalDuration);
    mReappearAnimator.addUpdateListener(mInvalidateUpdateListener);
  }
  public static ObjectAnimator getPulseAnimator(
      View labelToAnimate, float decreaseRatio, float increaseRatio) {
    Keyframe k0 = Keyframe.ofFloat(0f, 1f);
    Keyframe k1 = Keyframe.ofFloat(0.275f, decreaseRatio);
    Keyframe k2 = Keyframe.ofFloat(0.69f, increaseRatio);
    Keyframe k3 = Keyframe.ofFloat(1f, 1f);

    PropertyValuesHolder scaleX = PropertyValuesHolder.ofKeyframe("scaleX", k0, k1, k2, k3);
    PropertyValuesHolder scaleY = PropertyValuesHolder.ofKeyframe("scaleY", k0, k1, k2, k3);
    ObjectAnimator pulseAnimator =
        ObjectAnimator.ofPropertyValuesHolder(labelToAnimate, scaleX, scaleY);
    pulseAnimator.setDuration(PULSE_ANIMATOR_DURATION);

    return pulseAnimator;
  }
  public ObjectAnimator getReappearAnimator() {
    if (!this.mIsInitialized || !this.mDrawValuesReady) {
      Log.e(TAG, "RadialSelectorView was not ready for animation.");
      return null;
    }

    Keyframe kf0, kf1, kf2, kf3;
    float midwayPoint = 0.2f;
    int duration = 500;

    // The time points are half of what they would normally be, because this animation is
    // staggered against the disappear so they happen seamlessly. The reappear starts
    // halfway into the disappear.
    float delayMultiplier = 0.25f;
    float transitionDurationMultiplier = 1f;
    float totalDurationMultiplier = transitionDurationMultiplier + delayMultiplier;
    int totalDuration = (int) (duration * totalDurationMultiplier);
    float delayPoint = delayMultiplier * duration / totalDuration;
    midwayPoint = 1 - midwayPoint * (1 - delayPoint);

    kf0 = Keyframe.ofFloat(0f, this.mTransitionEndRadiusMultiplier);
    kf1 = Keyframe.ofFloat(delayPoint, this.mTransitionEndRadiusMultiplier);
    kf2 = Keyframe.ofFloat(midwayPoint, this.mTransitionMidRadiusMultiplier);
    kf3 = Keyframe.ofFloat(1f, 1);
    PropertyValuesHolder radiusReappear =
        PropertyValuesHolder.ofKeyframe("animationRadiusMultiplier", kf0, kf1, kf2, kf3);

    kf0 = Keyframe.ofFloat(0f, 0f);
    kf1 = Keyframe.ofFloat(delayPoint, 0f);
    kf2 = Keyframe.ofFloat(1f, 1f);
    PropertyValuesHolder fadeIn = PropertyValuesHolder.ofKeyframe("alpha", kf0, kf1, kf2);

    ObjectAnimator reappearAnimator =
        ObjectAnimator.ofPropertyValuesHolder(this, radiusReappear, fadeIn)
            .setDuration(totalDuration);
    reappearAnimator.addUpdateListener(this.mInvalidateUpdateListener);
    return reappearAnimator;
  }