android动画深入学习

android动画深入分析

分析ValueAnimator

ofInt的初始化工作

ValueAnimator anim = ValueAnimator.ofInt(0, 40);
anim.setDuration(40);
anim.addUpdateListener(new AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        // frameValue是通过startValue和endValue以及fraction计算出来的
        int frameValue = (Integer) animation.getAnimatedValue();
    }
});
anim.start();

下面一步步分析:
其中ValueAnimator.ofInt(0, 40);

//把values放在PropertyValuesHolder对象中,在ValueAnimator中操作的都是valuesHolder对象 
public static ValueAnimator ofInt(int... values) {  
    ValueAnimator anim = new ValueAnimator();  
    anim.setIntValues(values);  
    return anim;  
}  

public void setIntValues(int... values) {
    if (values == null || values.length == 0) {
        return;
    }
    if (mValues == null || mValues.length == 0) {
        setValues(PropertyValuesHolder.ofInt("", values));//没有target对象,所以没有属性名
    } else {
        //当前对象有多个PropertyValuesHolder时,把values值设置在第一个holder上
        PropertyValuesHolder valuesHolder = mValues[0];
        valuesHolder.setIntValues(values);
    }
    // New property/values/target should cause re-initialization prior to starting
    mInitialized = false;
}

public static PropertyValuesHolder ofInt(String propertyName, int... values) {  
    return new IntPropertyValuesHolder(propertyName, values);  
}

//继续看IntPropertyValuesHolder:
public IntPropertyValuesHolder(String propertyName, int... values) {  
    super(propertyName);  
    setIntValues(values);  
}  

@Override  
public void setIntValues(int... values) {  
    super.setIntValues(values);//调用了父类的setIntValues方法
    mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet;//产生了一个mKeyframeSet对象
}  

父类PropertyValueHolder的setIntValues方法:

public void setIntValues(int... values) {  
    mValueType = int.class;  
    mKeyframeSet = KeyframeSet.ofInt(values);  
}

KeyframeSet.onInt:

/** 
 * 从此方法可以看到,values数组中的每一个值都被包装成了IntKeyframe, 
 * IntKeyframe保存一个当前值的fraction,value和mValueType。 
 * IntKeyframeSet则保存是一组IntKeyframe的集合。 
 * @param values 
 * @return 
 */ 
public static KeyframeSet ofInt(int... values) {  
    int numKeyframes = values.length;  
    IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)];  
    if (numKeyframes == 1) {    //这里只可能是ObjectAnimator才会发生,  
        keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f);   //这里value为0,默认从ObjectAnimator中的目标对象中得到  
        keyframes[1] = (IntKeyframe) Keyframe.ofInt(1f, values[0]);  
    } else {  
        keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f, values[0]);  
        for (int i = 1; i < numKeyframes; ++i) {    //根据值个数拆分  
            keyframes[i] = (IntKeyframe) Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]);  
        }  
    }  
    return new IntKeyframeSet(keyframes);  
}  

由此可见,当初始化ValueAnimator时,同时也把传入的每一个数据值包装成了一个Keyframe,并保存在KeyframeSet中,而KeyframeSet则是在PropertyValueHolder初始化的。
调用start开始动画,调用AnimationHandler的start开始动画。在AnimationHandler中进行doAnimationFrame。它的每一帧调用是采用mChoreographer来控制,它处理回调的时机是屏幕的垂直同步Vsync事件来到之时,给它传入的回调过程可以被当作渲染下一帧工作的部分。

doAnimateFrame每一帧的工作

doAnimationFrame调用的是animationFrame,它里面计算了一个最初的fraction:
float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
然后调用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);
    }
    if (mUpdateListeners != null) {
        int numListeners = mUpdateListeners.size();
        for (int i = 0; i < numListeners; ++i) {
            mUpdateListeners.get(i).onAnimationUpdate(this);
        }
    }
}

//然后,PropertyValuesHolder.calculateValue(fraction):
void calculateValue(float fraction) {
    mAnimatedValue = mKeyframeSet.getValue(fraction);
}

//然后,IntKeyframeSet.getValue(fraction):
 public int getIntValue(float fraction) {
    if (mNumKeyframes == 2) {
        if (firstTime) {
            firstTime = false;
            firstValue = ((IntKeyframe) mKeyframes.get(0)).getIntValue();
            lastValue = ((IntKeyframe) mKeyframes.get(1)).getIntValue();
            deltaValue = lastValue - firstValue;
        }
        if (mInterpolator != null) {
            fraction = mInterpolator.getInterpolation(fraction);
        }
        if (mEvaluator == null) {
            return firstValue + (int)(fraction * deltaValue);
        } else {
            return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).intValue();
        }
    }
    if (fraction <= 0f) {
        final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0);
        final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(1);
        int prevValue = prevKeyframe.getIntValue();
        int nextValue = nextKeyframe.getIntValue();
        float prevFraction = prevKeyframe.getFraction();
        float nextFraction = nextKeyframe.getFraction();
        final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
        if (interpolator != null) {
            fraction = interpolator.getInterpolation(fraction);
        }
        float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
        return mEvaluator == null ?
                prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
                ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                        intValue();
    } else if (fraction >= 1f) {
        final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 2);
        final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 1);
        int prevValue = prevKeyframe.getIntValue();
        int nextValue = nextKeyframe.getIntValue();
        float prevFraction = prevKeyframe.getFraction();
        float nextFraction = nextKeyframe.getFraction();
        final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
        if (interpolator != null) {
            fraction = interpolator.getInterpolation(fraction);
        }
        float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
        return mEvaluator == null ?
                prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
                ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).intValue();
    }
    IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0);
    for (int i = 1; i < mNumKeyframes; ++i) {
        IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(i);
        if (fraction < nextKeyframe.getFraction()) {
            final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
            if (interpolator != null) {
                fraction = interpolator.getInterpolation(fraction);
            }
            float intervalFraction = (fraction - prevKeyframe.getFraction()) /
                (nextKeyframe.getFraction() - prevKeyframe.getFraction());
            int prevValue = prevKeyframe.getIntValue();
            int nextValue = nextKeyframe.getIntValue();
            return mEvaluator == null ?
                    prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
                    ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                            intValue();
        }
        prevKeyframe = nextKeyframe;
    }
    // shouldn't get here
    return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).intValue();
}

分析ObjectAnimator

初始化工作

public static ObjectAnimator ofInt(Object target, String propertyName, int... values) {
    ObjectAnimator anim = new ObjectAnimator(target, propertyName);
    anim.setIntValues(values);
    return anim;
}

//
public void setIntValues(int... values) {
    if (mValues == null || mValues.length == 0) {
        // No values yet - this animator is being constructed piecemeal. Init the values with
        // whatever the current propertyName is
        if (mProperty != null) {
            setValues(PropertyValuesHolder.ofInt(mProperty, values));
        } else {
            setValues(PropertyValuesHolder.ofInt(mPropertyName, values));
        }
    } else {
        super.setIntValues(values);
    }
}

//下面的和ValueAnimator那边用的一样

//看PropertyValuesHolder.ofInt(mPropertyName, values):
public static PropertyValuesHolder ofInt(String propertyName, int... values) {
    return new IntPropertyValuesHolder(propertyName, values);
}

//然后继续ObjectAnimator.setValues:
public void setValues(PropertyValuesHolder... values) {
    int numValues = values.length;
    mValues = values;
    mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
    for (int i = 0; i < numValues; ++i) {
        PropertyValuesHolder valuesHolder = values[i];
        mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
    }
    // New property/values/target should cause re-initialization prior to starting
    mInitialized = false;
}

//在initAnimation中调用PropertyValuesHolder.setupSetterAndGetter:
 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.
        int numValues = mValues.length;
        for (int i = 0; i < numValues; ++i) {
            mValues[i].setupSetterAndGetter(mTarget);//设置好mSetter函数
        }
        super.initAnimation();
    }
}

到这里初始化就完成了,相对于ValueAninator,多设置了target和propertyName,以及setter函数。

每一帧的工作

//设置值
void animateValue(float fraction) {
    super.animateValue(fraction);//计算好animateValue值
    int numValues = mValues.length;
    for (int i = 0; i < numValues; ++i) {
        mValues[i].setAnimatedValue(mTarget);
    }
}

void setAnimatedValue(Object target) {
    if (mProperty != null) {
        mProperty.set(target, getAnimatedValue());
    }
    if (mSetter != null) {
        try {
            mTmpValueArray[0] = getAnimatedValue();//取出计算好的int值
            mSetter.invoke(target, mTmpValueArray);//设置到set函数上去
        } catch (InvocationTargetException e) {
            Log.e("PropertyValuesHolder", e.toString());
        } catch (IllegalAccessException e) {
            Log.e("PropertyValuesHolder", e.toString());
        }
    }
}

分析ViewPropertyAnimator

有mView,mDuration,mStartDelay,mInterpolator,mListener,mUpdateListener,mPendingAnimations
操作是固定的:TRANSLATION_X/TRANSLATION_Y/SCALE_X/SCALE_X/ROTATION/ALPHA
ViewPropertyAnimator.startAnimation中启动了一个ValueAniamtor来进行动画:

private void startAnimation() {
    mView.setHasTransientState(true);
    ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
    ArrayList<NameValuesHolder> nameValueList =
            (ArrayList<NameValuesHolder>) mPendingAnimations.clone();
    mPendingAnimations.clear();
    int propertyMask = 0;
    int propertyCount = nameValueList.size();
    for (int i = 0; i < propertyCount; ++i) {
        NameValuesHolder nameValuesHolder = nameValueList.get(i);
        propertyMask |= nameValuesHolder.mNameConstant;
    }
    mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
    if (mPendingSetupAction != null) {
        mAnimatorSetupMap.put(animator, mPendingSetupAction);
        mPendingSetupAction = null;
    }
    if (mPendingCleanupAction != null) {
        mAnimatorCleanupMap.put(animator, mPendingCleanupAction);
        mPendingCleanupAction = null;
    }
    if (mPendingOnStartAction != null) {
        mAnimatorOnStartMap.put(animator, mPendingOnStartAction);
        mPendingOnStartAction = null;
    }
    if (mPendingOnEndAction != null) {
        mAnimatorOnEndMap.put(animator, mPendingOnEndAction);
        mPendingOnEndAction = null;
    }
    //动画操作是在mAnimatorEventListener中的onAnimationUpdate中完成的
    animator.addUpdateListener(mAnimatorEventListener);
    animator.addListener(mAnimatorEventListener);
    if (mStartDelaySet) {
        animator.setStartDelay(mStartDelay);
    }
    if (mDurationSet) {
        animator.setDuration(mDuration);
    }
    if (mInterpolatorSet) {
        animator.setInterpolator(mInterpolator);
    }
    animator.start();
}

分析AnimatorSet

参考:

http://zhouyunan2010.iteye.com/blog/1972789

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值