本文主要解決如下問題: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
感謝觀看,有不對的地方,歡迎你們指出~~