Android属性动画源码解析

核心类

PropertyValuesHolder  (可以根据时间比例从Keyframes    获取到指定的值,可以提供访问指定属性的方法)
该类保存有关属性及其值的信息
在动画中播放。PropertyValuesHolder对象可用于创建
动画与ValueAnimator或ObjectAnimator操作几个不同的属性并行。

Keyframes   储存关键帧的集合,  并且可以根据动画的时间比例,获取当前做动画的值
实现类KeyframeSet
核心方法getValue     根据时间比例,找到对应的关键帧,然后调用关键帧的插值器,返回变化比例,再把关键帧,和变化比例,传递给估值器,计算出应该变化多少
 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();
                final float prevFraction = prevKeyframe.getFraction();
                float intervalFraction = (fraction - prevFraction) /
                    (nextKeyframe.getFraction() - prevFraction);
                // Apply interpolator on the proportional duration.
                if (interpolator != null) {
                    intervalFraction = interpolator.getInterpolation(intervalFraction);
                }
                return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
                        nextKeyframe.getValue());
            }
            prevKeyframe = nextKeyframe;
        }
        // shouldn't reach here
        return mLastKeyframe.getValue();
    }

Keyframe  一帧的属性封装,储存,当前帧的,触发时间比例,值,值的类型,还有插值器


TypeEvaluator 估值器,根据fraction,和start和end,计算出应该做动画的具体值


分析值动画执行流程

 ValueAnimator animator = ValueAnimator.ofInt(0,3);
        //如下传入多个参数,效果则为0->5,5->3,3->10
        //ValueAnimator animator = ValueAnimator.ofInt(0,5,3,10);

        //设置动画的基础属性
        animator.setDuration(5000);//播放时长
        animator.setStartDelay(300);//延迟播放
        animator.setRepeatCount(0);//重放次数
        animator.setRepeatMode(ValueAnimator.RESTART);
        //重放模式
        //ValueAnimator.START:正序
        //ValueAnimator.REVERSE:倒序

        //设置更新监听
        //值 改变一次,该方法就执行一次
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            //获取改变后的值
            int currentValue = (int) animation.getAnimatedValue();
            //输出改变后的值
            Log.d("1111", "onAnimationUpdate: " + currentValue);

            //改变后的值发赋值给对象的属性值
            //view.setproperty(currentValue);

            //刷新视图
            //view.requestLayout();
          }
        });
        //启动动画
        animator.start();


开始
 ValueAnimator animator = ValueAnimator.ofInt(0,3);

   public static ValueAnimator ofInt(int... values) {
        ValueAnimator anim = new ValueAnimator();//创建值动画
        anim.setIntValues(values);//为值动画设置关键值,方法内部会根据值类型使用对应的KeyFrame,和KeyFramesSet类
        return anim;
    }

->anim.setIntValues(values)

public void setIntValues(int... values) {
        if (values == null || values.length == 0) {
            return;
        }
        if (mValues == null || mValues.length == 0) {
            setValues(PropertyValuesHolder.ofInt("", values));//创建int类型的PropertyValuesHolder然后设置到ValueAnimator中
        } else {
            PropertyValuesHolder valuesHolder = mValues[0];
            valuesHolder.setIntValues(values);
        }
        // New property/values/target should cause re-initialization prior to starting
        mInitialized = false;
    }
->PropertyValuesHolder.ofInt("", values)
  public static PropertyValuesHolder ofInt(String propertyName, int... values) {
        return new IntPropertyValuesHolder(propertyName, values);
    }
->new IntPropertyValuesHolder(propertyName, values);
public IntPropertyValuesHolder(String propertyName, int... values) {
            super(propertyName);
            setIntValues(values);
        }
->IntPropertyValuesHolder.setIntValues(values);

  public void setIntValues(int... values) {
            super.setIntValues(values);
            mIntKeyframes = (Keyframes.IntKeyframes) mKeyframes;
        }
->PropertyValuesHolder.setIntValues(values);
public void setIntValues(int... values) {
        mValueType = int.class;
        mKeyframes = KeyframeSet.ofInt(values);//根据生成对应类型的 KeyframeSet,分析到这里就算设置上去了,再返回到这里,算是生成了PropertyValuesHolder
    }
然后设置到ValueAnimator上
继续
 setValues(PropertyValuesHolder.ofInt("", values));
public void setValues(PropertyValuesHolder... values) {
        int numValues = values.length;
        mValues = values;                                          //把(PropertyValuesHolder 数组保存到数组中
        mValuesMap = new HashMap(numValues);
        for (int i = 0; i < numValues; ++i) {
            PropertyValuesHolder valuesHolder = values[i];
            mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);               //属性名称作为key,PropertyValuesHolder作为key 保存到map中
        }
        // New property/values/target should cause re-initialization prior to starting
        mInitialized = false;
    }
然后中间就是设置时间等等简单的动画属性,就不在分析,
现在分析start()方法
-》valueAnimator.start()
public void start() {
        start(false);
    }
->  start(false);
private void start(boolean playBackwards) {
        if (Looper.myLooper() == null) {
            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
        }
        mReversing = playBackwards;
        mPlayingBackwards = playBackwards;
        if (playBackwards && mSeekFraction != -1) {
            if (mSeekFraction == 0 && mCurrentIteration == 0) {
                // special case: reversing from seek-to-0 should act as if not seeked at all
                mSeekFraction = 0;
            } else if (mRepeatCount == INFINITE) {
                mSeekFraction = 1 - (mSeekFraction % 1);
            } else {
                mSeekFraction = 1 + mRepeatCount - (mCurrentIteration + mSeekFraction);
            }
            mCurrentIteration = (int) mSeekFraction;
            mSeekFraction = mSeekFraction % 1;
        }
        if (mCurrentIteration > 0 && mRepeatMode == REVERSE &&
                (mCurrentIteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) {
            // if we were seeked to some other iteration in a reversing animator,
            // figure out the correct direction to start playing based on the iteration
            if (playBackwards) {
                mPlayingBackwards = (mCurrentIteration % 2) == 0;
            } else {
                mPlayingBackwards = (mCurrentIteration % 2) != 0;
            }
        }
        int prevPlayingState = mPlayingState;
        mPlayingState = STOPPED;
        mStarted = true;
        mStartedDelay = false;
        mPaused = false;
        updateScaledDuration(); // in case the scale factor has changed since creation time
        AnimationHandler animationHandler = getOrCreateAnimationHandler();    //获取了一个本线程的 AnimationHandler 
        animationHandler.mPendingAnimations.add(this);                                       //把ValueAnimator加入到 animationHandler.mPendingAnimations,一个即将执行的动画集合
        if (mStartDelay == 0) {
            // This sets the initial value of the animation, prior to actually starting it running
            if (prevPlayingState != SEEKED) {
                setCurrentPlayTime(0);
            }
            mPlayingState = STOPPED;
            mRunning = true;
            notifyStartListeners();
        }
        animationHandler.start();                                                                                 //然后执行 animationHandler的start方法
    }
-》        animationHandler.start();             
    public void start() {
            scheduleAnimation();
        }
-》animationHandler.scheduleAnimation();
   private void scheduleAnimation() {
            if (!mAnimationScheduled) {
                mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimate, null);//使用舞蹈指挥者,请求绘制信号,并且再绘制来临的时候执行回调mAnimate, 
                mAnimationScheduled = true;
            }
        }
-》animationHandler.mAnimate, 
 final Runnable mAnimate = new Runnable() {
            @Override
            public void run() {
                mAnimationScheduled = false;
                doAnimationFrame(mChoreographer.getFrameTime());
            }
        };
-》animationHandler. doAnimationFrame(mChoreographer.getFrameTime());//不断的回调方法,执行
mPendingAnimations 存储要开始的动画
void doAnimationFrame(long frameTime) {
            mLastFrameTime = frameTime;

            // mPendingAnimations holds any animations that have requested to be started
            // We're going to clear mPendingAnimations, 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 mPendingAnimations
            // is empty.
            while (mPendingAnimations.size() > 0) {
                ArrayList pendingCopy =
                        (ArrayList) mPendingAnimations.clone();
                mPendingAnimations.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(this);                  //开始执行动画ValueAnimtor.startAnimation(this);           
                    } else {
                        mDelayedAnims.add(anim);           //如果有延时开始,就先放到,延时开始集合
                    }
                }
            }

            // Next, process animations currently sitting on the delayed queue, adding
            // them to the active animations if they are ready
            int numDelayedAnims = mDelayedAnims.size();
            for (int i = 0; i < numDelayedAnims; ++i) {                   //检查延时开始集合,是否可以开始,如果可以开始了,就放到 mReadyAnims准备就绪集合
                ValueAnimator anim = mDelayedAnims.get(i);
                if (anim.delayedAnimationFrame(frameTime)) {
                    mReadyAnims.add(anim);
                }
            }
            int numReadyAnims = mReadyAnims.size();
            if (numReadyAnims > 0) {
                for (int i = 0; i < numReadyAnims; ++i) {                           //开始准备就绪集合中的动画
                    ValueAnimator anim = mReadyAnims.get(i);
                    anim.startAnimation(this);
                    anim.mRunning = true;
                    mDelayedAnims.remove(anim);                             //并从延迟中删除
                }
                mReadyAnims.clear();                                                  //开始后清楚
            }

            // Now process all active animations. The return value from animationFrame()    // mAnimations 正在执行中的动画
            // tells the handler whether it should now be ended
            int numAnims = mAnimations.size();
            for (int i = 0; i < numAnims; ++i) {
                mTmpAnimations.add(mAnimations.get(i));
            }
            for (int i = 0; i < numAnims; ++i) {
                ValueAnimator anim = mTmpAnimations.get(i);
                if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {    //  anim.doAnimationFrame(frameTime)这里是真正的执行动画动作,如果已经结束,返回true
                    mEndingAnims.add(anim);                  //对于已经结束的动画,添加到结束动画集合
                }
            }
            mTmpAnimations.clear();
            if (mEndingAnims.size() > 0) {
                for (int i = 0; i < mEndingAnims.size(); ++i) {
                    mEndingAnims.get(i).endAnimation(this);                         //对于已经结束的动画,执行结束方法
                }
                mEndingAnims.clear();
            }

            // Schedule final commit for the frame.
            mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, mCommit, null);  //再这个回调中,是第一帧执行完之后,调整开始时间

            // If there are still active or delayed animations, schedule a future call to
            // onAnimate to process the next frame of the animations.
            if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {//检查,如果动画还没有做完,就再去请求绘制信号,重复上面的回调
                scheduleAnimation();                       //重新来一遍
            }
        }


动画分为两个步骤
1.设置数据,组建数据
2.开始执行流程
执行流程,主要再start开始然后不断回调AnimatorHandler.doAnimationFrame()然后再这个方法中,调用ValueAnimor的方法,依次是


anim.startAnimation(this);  


anim.doAnimationFrame(frameTime)


mEndingAnims.get(i).endAnimation(this);  

然后就可以具体分析了anim.startAnimation(this);  
 private void startAnimation(AnimationHandler handler) {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
            Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(),
                    System.identityHashCode(this));
        }
        initAnimation();              //初始化动画
        handler.mAnimations.add(this);//把自己添加到执行中集合
        if (mStartDelay > 0 && mListeners != null) {
            // Listeners were already notified in start() if startDelay is 0; this is
            // just for delayed animations
            notifyStartListeners();//通知开始执行动画监听
        }
    }
-》
   void initAnimation() {
        if (!mInitialized) {
            int numValues = mValues.length;
            for (int i = 0; i < numValues; ++i) {
                mValues[i].init();//初始化所有的 PropertyValuesHolder  
            }
            mInitialized = true;
        }
    }

监听就不分析了

分析anim.doAnimationFrame(frameTime)
 final boolean doAnimationFrame(long frameTime) {
        if (mPlayingState == STOPPED) {
            mPlayingState = RUNNING;
            if (mSeekFraction < 0) {
                mStartTime = frameTime;
            } else {
                long seekTime = (long) (mDuration * mSeekFraction);
                mStartTime = frameTime - seekTime;
                mSeekFraction = -1;
            }
            mStartTimeCommitted = false; // allow start time to be compensated for jank
        }
        if (mPaused) {
            if (mPauseTime < 0) {
                mPauseTime = frameTime;
            }
            return false;
        } else if (mResumed) {
            mResumed = false;
            if (mPauseTime > 0) {
                // Offset by the duration that the animation was paused
                mStartTime += (frameTime - mPauseTime);
                mStartTimeCommitted = false; // allow start time to be compensated for jank
            }
        }
        // The frame time might be before the start time during the first frame of
        // an animation.  The "current time" must always be on or after the start
        // time to avoid animating frames at negative time intervals.  In practice, this
        // is very rare and only happens when seeking backwards.
        final long currentTime = Math.max(frameTime, mStartTime);
        return animationFrame(currentTime);
    }
-》 animationFrame(currentTime);


boolean animationFrame(long currentTime) {//具体执行动画
        boolean done = false;
        switch (mPlayingState) {
        case RUNNING:
        case SEEKED:
            float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
            if (mDuration == 0 && mRepeatCount != INFINITE) {
                // Skip to the end
                mCurrentIteration = mRepeatCount;
                if (!mReversing) {
                    mPlayingBackwards = false;
                }
            }
            if (fraction >= 1f) {
                if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
                    // Time to repeat
                    if (mListeners != null) {
                        int numListeners = mListeners.size();
                        for (int i = 0; i < numListeners; ++i) {
                            mListeners.get(i).onAnimationRepeat(this);
                        }
                    }
                    if (mRepeatMode == REVERSE) {
                        mPlayingBackwards = !mPlayingBackwards;
                    }
                    mCurrentIteration += (int) fraction;
                    fraction = fraction % 1f;
                    mStartTime += mDuration;
                    // Note: We do not need to update the value of mStartTimeCommitted here
                    // since we just added a duration offset.
                } else {
                    done = true;
                    fraction = Math.min(fraction, 1.0f);
                }
            }
            if (mPlayingBackwards) {
                fraction = 1f - fraction;
            }
            animateValue(fraction);//执行动画
            break;
        }

        return done;
    }
-》   animateValue(fraction);

void animateValue(float fraction) {
        fraction = mInterpolator.getInterpolation(fraction);//根据时间比例调用默认插值器
        mCurrentFraction = fraction;
        int numValues = mValues.length;
        for (int i = 0; i < numValues; ++i) {
            mValues[i].calculateValue(fraction);//调用所有的PropertyValuesHolder  的计算属性值
        }
        if (mUpdateListeners != null) {
            int numListeners = mUpdateListeners.size();
            for (int i = 0; i < numListeners; ++i) {
                mUpdateListeners.get(i).onAnimationUpdate(this);   //执行更新监听,然后调用ValueAnimator.getAnimatedValue 获取计算的动画值然后设置
            }
        }
    }


ValueAnimator分析完毕

对于ObjectAnimator继承ValueAnimator,主要添加的功能就是通过,PropertyValuesHolder,设置动画的初始值,结束值,和动画中的值
主要重写了几个方法

    
   void initAnimation()
void initAnimation() {
        if (!mInitialized) {
            // mValueType may change due to setter/getter setup; do this before calling super.init(),
            // which uses mValueType to set up the default type evaluator.
            final Object target = getTarget();
            if (target != null) {
                final int numValues = mValues.length;
                for (int i = 0; i < numValues; ++i) {
                    mValues[i].setupSetterAndGetter(target);//主要添加了,如果动画,没有设置初始值,就会从target中读取当前属性的值作为初始值
                }
            }
            super.initAnimation();
        }
    }


  public void setupStartValues() 
 public void setupStartValues() {
        initAnimation();

        final Object target = getTarget();
        if (target != null) {
            final int numValues = mValues.length;
            for (int i = 0; i < numValues; ++i) {
                mValues[i].setupStartValue(target);//为目标对象设置初始值,第一镇的第一个值
            }
        }
    }


   public void setupEndValues()
public void setupEndValues() {
        initAnimation();

        final Object target = getTarget();
        if (target != null) {
            final int numValues = mValues.length;
            for (int i = 0; i < numValues; ++i) {
                mValues[i].setupEndValue(target);//设置最终值,为目标对象
            }
        }
    }


 void animateValue(float fraction)//做动画的回调,再这个方法中调用PropertyValuesHolder的设置值的方法
    void animateValue(float fraction) {
        final Object target = getTarget();
        if (mTarget != null && target == null) {
            // We lost the target reference, cancel and clean up.
            cancel();
            return;
        }

        super.animateValue(fraction);
        int numValues = mValues.length;
        for (int i = 0; i < numValues; ++i) {
            mValues[i].setAnimatedValue(target);//设置动画值
        }
    }

你可能感兴趣的:(android源码)