Пример #1
0
 /**
  * Sets the position of the animation to the specified point in time. This time should be between
  * 0 and the total duration of the animation, including any repetition. If the animation has not
  * yet been started, then it will not advance forward after it is set to this time; it will simply
  * set the time to this value and perform any appropriate actions based on that time. If the
  * animation is already running, then setCurrentPlayTime() will set the current playing time to
  * this value and continue playing from that point.
  *
  * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
  */
 public void setCurrentPlayTime(long playTime) {
   initAnimation();
   long currentTime = AnimationUtils.currentAnimationTimeMillis();
   if (mPlayingState != RUNNING) {
     mSeekTime = playTime;
     mPlayingState = SEEKED;
   }
   mStartTime = currentTime - playTime;
   animationFrame(currentTime);
 }
Пример #2
0
    /**
     * There are only two messages that we care about: ANIMATION_START and ANIMATION_FRAME. The
     * START message is sent when an animation's start() method is called. It cannot start
     * synchronously when start() is called because the call may be on the wrong thread, and it
     * would also not be synchronized with other animations because it would not start on a common
     * timing pulse. So each animation sends a START message to the handler, which causes the
     * handler to place the animation on the active animations queue and start processing frames for
     * that animation. The FRAME message is the one that is sent over and over while there are any
     * active animations to process.
     */
    public void handleMessage(Message msg) {
      boolean callAgain = true;
      ArrayList<ValueAnimator> animations = sAnimations.get();
      ArrayList<ValueAnimator> delayedAnims = sDelayedAnims.get();
      switch (msg.what) {
          // TODO: should we avoid sending frame message when starting if we
          // were already running?
        case ANIMATION_START:
          ArrayList<ValueAnimator> pendingAnimations = sPendingAnimations.get();
          if (animations.size() > 0 || delayedAnims.size() > 0) {
            callAgain = false;
          }
          // pendingAnims holds any animations that have requested to be started
          // We're going to clear sPendingAnimations, but starting animation may
          // cause more to be added to the pending list (for example, if one animation
          // starting triggers another starting). So we loop until sPendingAnimations
          // is empty.
          while (pendingAnimations.size() > 0) {
            ArrayList<ValueAnimator> pendingCopy =
                (ArrayList<ValueAnimator>) pendingAnimations.clone();
            pendingAnimations.clear();
            int count = pendingCopy.size();
            for (int i = 0; i < count; ++i) {
              ValueAnimator anim = pendingCopy.get(i);
              // If the animation has a startDelay, place it on the delayed list
              if (anim.mStartDelay == 0) {
                anim.startAnimation();
              } else {
                delayedAnims.add(anim);
              }
            }
          }
          // fall through to process first frame of new animations
        case ANIMATION_FRAME:
          // currentTime holds the common time for all animations processed
          // during this frame
          long currentTime = AnimationUtils.currentAnimationTimeMillis();
          ArrayList<ValueAnimator> readyAnims = sReadyAnims.get();
          ArrayList<ValueAnimator> endingAnims = sEndingAnims.get();

          // First, process animations currently sitting on the delayed queue, adding
          // them to the active animations if they are ready
          int numDelayedAnims = delayedAnims.size();
          for (int i = 0; i < numDelayedAnims; ++i) {
            ValueAnimator anim = delayedAnims.get(i);
            if (anim.delayedAnimationFrame(currentTime)) {
              readyAnims.add(anim);
            }
          }
          int numReadyAnims = readyAnims.size();
          if (numReadyAnims > 0) {
            for (int i = 0; i < numReadyAnims; ++i) {
              ValueAnimator anim = readyAnims.get(i);
              anim.startAnimation();
              anim.mRunning = true;
              delayedAnims.remove(anim);
            }
            readyAnims.clear();
          }

          // Now process all active animations. The return value from animationFrame()
          // tells the handler whether it should now be ended
          int numAnims = animations.size();
          int i = 0;
          while (i < numAnims) {
            ValueAnimator anim = animations.get(i);
            if (anim.animationFrame(currentTime)) {
              endingAnims.add(anim);
            }
            if (animations.size() == numAnims) {
              ++i;
            } else {
              // An animation might be canceled or ended by client code
              // during the animation frame. Check to see if this happened by
              // seeing whether the current index is the same as it was before
              // calling animationFrame(). Another approach would be to copy
              // animations to a temporary list and process that list instead,
              // but that entails garbage and processing overhead that would
              // be nice to avoid.
              --numAnims;
              endingAnims.remove(anim);
            }
          }
          if (endingAnims.size() > 0) {
            for (i = 0; i < endingAnims.size(); ++i) {
              endingAnims.get(i).endAnimation();
            }
            endingAnims.clear();
          }

          // If there are still active or delayed animations, call the handler again
          // after the frameDelay
          if (callAgain && (!animations.isEmpty() || !delayedAnims.isEmpty())) {
            sendEmptyMessageDelayed(
                ANIMATION_FRAME,
                Math.max(
                    0, sFrameDelay - (AnimationUtils.currentAnimationTimeMillis() - currentTime)));
          }
          break;
      }
    }