本文主要解决如下问题:java
好了,接下来,开始打怪~数组
首先,咱们平时写属性动画是这么写的:框架
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(v,"scaleX",0,1);
objectAnimator.setEvaluator(new FloatEvaluator());
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setDuration(1000);
objectAnimator.start();
复制代码
so,咱们先从ofFloat
开始ide
//一、入口
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
ObjectAnimator anim = new ObjectAnimator(target, propertyName);
anim.setFloatValues(values);
return anim;
}
//二、看new ObjectAnimator作了什么?
private ObjectAnimator(Object target, String propertyName) {
setTarget(target);
setPropertyName(propertyName);
}
//三、setTarget 进去look look
@Override
public void setTarget(@Nullable Object target) {
.....
//就弱引用,没啥
mTarget = target == null ? null : new WeakReference<Object>(target);
....
}
}
//四、setPropertyName 瞄瞄
public void setPropertyName(@NonNull String propertyName) {
......
//依旧只是保存值
mPropertyName = propertyName;
......
}
// 五、看看anim.setFloatValues(values) 干了啥
@Override
public void setFloatValues(float... values) {
if (mValues == null || mValues.length == 0) {
if (mProperty != null) {
//注意注意,重点人物之一的PropertyValuesHolder出现了!!!
setValues(PropertyValuesHolder.ofFloat(mProperty, values));
} else {
setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
}
} else {
super.setFloatValues(values);
}
}
//六、跟踪 PropertyValuesHolder.ofFloat 方法,最终会调用setFloatValues这个方法
public void setFloatValues(float... values) {
mValueType = float.class;
//注意注意,重点人物 KeyframeSet 也出现了!!!
mKeyframes = KeyframeSet.ofFloat(values);
}
// 七、跟踪KeyframeSet.ofFloat方法
public static KeyframeSet ofFloat(float... values) {
.....
int numKeyframes = values.length;
FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)];
if (numKeyframes == 1) {
.....
} else {
//能够看到,这里根据values的长度,构造了keyframes数组,
//而后分别经过Keyframe的ofFloat方法,去构造keyframe对象
//Keyframe就是关键帧,它里面保存了类型、数值以及估值器
keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]);
for (int i = 1; i < numKeyframes; ++i) {
keyframes[i] =
(FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);
if (Float.isNaN(values[i])) {
badValue = true;
}
}
}
......
return new FloatKeyframeSet(keyframes);
}
// 九、仍是大家看一个Keyframes源码吧,其实就是一个接口
public interface Keyframes extends Cloneable {
void setEvaluator(TypeEvaluator evaluator);
Class getType();
Object getValue(float fraction);
List<Keyframe> getKeyframes();
Keyframes clone() .... } 复制代码
第一步咱们就跟完了,咱们看到,在初始化的整个过程当中,涉及到了如下几个对象:oop
而这几个对象就构成了咱们属性动画的框架。post
接下来,咱们要来看一下咱们的view是怎么动起来的~动画
//一、从 objectAnimator.start()进入
public void start() {
AnimationHandler.getInstance().autoCancelBasedOn(this);
.....
super.start();
}
//二、点击super.start()一路跟到ValueAnimator的start(playBackwrds)方法
private void start(boolean playBackwards) {
.....
//跟踪这个方法
addAnimationCallback(0);
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
......
//这个方法其实就是去初始化Animation,这里就不跟踪了
//小伙伴能够进行去阅读
startAnimation();
if (mSeekFraction == -1) {
.....
setCurrentPlayTime(0);
} else {
setCurrentFraction(mSeekFraction);
}
}
}
//三、跟踪 addAnimationCallback(0)方法 ,最后能够来到AnimationHandler中的addAnimationFrameCallback方法
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
//这里发送了一个mFrameCallback,跟一下mFrameCallback
if (mAnimationCallbacks.size() == 0) {
getProvider().postFrameCallback(mFrameCallback);
}
//在这里添加了一个callback,而且这个callback是ValueAnimator!!记住,很重要!!
if (!mAnimationCallbacks.contains(callback)) {
mAnimationCallbacks.add(callback);
}
....
}
//四、mFrameCallback
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
//五、看Choreographer.FrameCallback的定义
/** * Implement this interface to receive a callback when a new display frame is * being rendered. The callback is invoked on the {@link Looper} thread to * which the {@link Choreographer} is attached. */
public interface FrameCallback {
/** * Called when a new display frame is being rendered. * <p> * 也就是说,每次从新开始渲染屏幕上的帧时,这个方法将会被调用。 */
public void doFrame(long frameTimeNanos);
}
//六、那这个doFrame方法在哪里被调用呢?用doFrame做为关键字在Choreographer查找,最后发现,在这里进行了调用
private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
super(looper, vsyncSource);
}
//看到熟悉的Vysnc没,从字眼咱们也大概能够推断,
//每次Vysnc信号来时,都会回调这个方法,最终会执行run()方法里面的代码
//最后,回调回去咱们的Choreographer.FrameCallback的doFrame方法
//这个回调的频率大概是16ms一次
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
....
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}
//七、这一段追完了,回去咱们的 mFrameCallback
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos){
//跟进这个方法
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
//八、 doAnimationFrame
private void doAnimationFrame(long frameTime) {
long currentTime = SystemClock.uptimeMillis();
final int size = mAnimationCallbacks.size();
for (int i = 0; i < size; i++) {
final AnimationFrameCallback callback = mAnimationCallbacks.get(i);
if (callback == null) {
continue;
}
if (isCallbackDue(callback, currentTime)) {
//还记得前面add了个callback吗?那个callback是ValueAnimator,因此,如今咱们要去看一下ValueAnimator的doAnimationFrame方法了
callback.doAnimationFrame(frameTime);
.....
}
}
....
}
//九、 ValueAnimator的doAnimationFrame ,还有几步就完了,坚持一下
public final boolean doAnimationFrame(long frameTime) {
....
//重点在这个方法
boolean finished = animateBasedOnTime(currentTime);
....
return finished;
}
//十、animateBasedOnTime
boolean animateBasedOnTime(long currentTime) {
....
//跟进这个方法,这里要注意,若是直接点击去,会去到ValueAnimator里面的animateValue,
//可是实际上,ObjectAnimator覆盖了这个方法,因此咱们要去看ObjectAnimator的animateValue方法
animateValue(currentIterationFraction);
....
}
//十一、ObjectAnimator的animateValue方法
@Override
void animateValue(float fraction) {
....
//super.animateValue能够本身去跟,其实就是利用interpolator和evaluator计算出当前动画对应的数值
super.animateValue(fraction);
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
//看这个setAnimatedValue方法
mValues[i].setAnimatedValue(target);
}
}
、、12、PropertyValuesHolder的 setAnimatedValue void setAnimatedValue(Object target) {
if (mProperty != null) {
mProperty.set(target, getAnimatedValue());
}
if (mSetter != null) {
try {
mTmpValueArray[0] = getAnimatedValue();
//看到没,其实就是经过反射动态调用setXX方法
//经过set方法去动态改变View的属性,从而实现动画效果
mSetter.invoke(target, mTmpValueArray);
} ...
}
}
复制代码
呼,累死了~~ui
到这里,让view动起来的整个流程就结束了。总结一下:this
ValueAnimator
的doAnimationFrame
方法Interpolator
和Evaluator
计算出当前动画的百分比和具体数值PropertyValuesHolder
的setAnimatedValue
方法,去反射调用setXX
,从而实现动态改变view的属性简化后的流程就是:lua
感谢观看,有不对的地方,欢迎你们指出~~