核心类
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
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
(ArrayList
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);//设置动画值
}
}
,