/** Animation step. */
  public void run() {
    long now = System.currentTimeMillis();
    long timeLeft = mTargetTime - now;
    if (timeLeft < 0) {
      mDimmingSpan.setAlpha(mDimming ? MIN_ALPHA : MAX_ALPHA);
      mAnimating = false;
      onAnimationEnded();
      return;
    }

    // Start=1, end=0
    float virtualTime = (float) timeLeft / mDuration;
    if (mDimming) {
      float interpolatedTime = DECELERATE_INTERPOLATOR.getInterpolation(virtualTime);
      mDimmingSpan.setAlpha((int) (MIN_ALPHA + (MAX_ALPHA - MIN_ALPHA) * interpolatedTime));
    } else {
      float interpolatedTime = ACCELERATE_INTERPOLATOR.getInterpolation(virtualTime);
      mDimmingSpan.setAlpha((int) (MIN_ALPHA + (MAX_ALPHA - MIN_ALPHA) * (1 - interpolatedTime)));
    }

    invalidate();

    // Repeat
    mHandler.postDelayed(this, FRAME_RATE);
  }
 /** Constructor. */
 public TextHighlightingAnimation(int duration) {
   mDuration = duration;
   mHandler = new Handler();
   mDimmingSpan = new DimmingSpan();
   mDimmingSpan.setAlpha(MAX_ALPHA);
 }