這里從最基本的使用分析源碼,平時我們使用屬性動畫如下:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tv,"alpha",1.0f,0.3f,1.0f);//初始化動畫
objectAnimator.setDuration(200);
objectAnimator.start();//動畫開始時從start方法開始的
先來分析下ofFloat
這個方法,這個方法是在ObjectAnimator
這個類中,如下:
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
ObjectAnimator anim = new ObjectAnimator(target, propertyName);//實例化ObjectAnimator
anim.setFloatValues(values);//設置屬性值
return anim;
}
這個方法做了兩件事:
1)實例化了ObjectAnimator
這個對象
首先看下ObjectAnimator
這個構造方法:
private ObjectAnimator(Object target, String propertyName) {
setTarget(target);//保存要執行對象的動畫
setPropertyName(propertyName);//設置要執行動畫的對象的屬性
}
看下setTarget
這個方法:
@Override
public void setTarget(@Nullable Object target) {
final Object oldTarget = getTarget();
if (oldTarget != target) {
if (isStarted()) {
cancel();
}
//將傳入的目標對象使用WeakReference包裹,然后賦值給mTarget
mTarget = target == null ? null : new WeakReference<Object>(target);
// New target should cause re-initialization prior to starting
//設置新的目標對象會導致動畫在啟動之前重新初始化
mInitialized = false;
}
}
然后返回看下ObjectAnimator
這個構造方法中的setPropertyName
這個方法:
public void setProperty(@NonNull Property property) {
if (mValues != null) {
//這里可以看到使用PropertyValuesHolder對屬性值進行了保存
PropertyValuesHolder valuesHolder = mValues[0];
String oldName = valuesHolder.getPropertyName();
valuesHolder.setProperty(property);
mValuesMap.remove(oldName);
mValuesMap.put(mPropertyName, valuesHolder);
}
if (mProperty != null) {
mPropertyName = property.getName();
}
mProperty = property;
//mInitialized還是false
mInitialized = false;
}
2)對動畫設置屬性值
我們查看一下setFloatValues
這個方法,這個方法是設置屬性和屬性值,核心代碼如下:
if (mProperty != null) {
setValues(PropertyValuesHolder.ofFloat(mProperty, values));
} else {
setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
}
PropertyValuesHolder
是屬性值持有者,它保存了動畫過程中所需要操作的屬性和對應的值,我們通過ofFloat()構造的動畫,ofFloat()的內部實現其實就是將傳進來的參數封裝成PropertyValuesHolder實例化來保存動畫的值
接著先看下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);
}
mInitialized = false;
}
可以看到將屬性值保存到了HashMap中,然后返回看下PropertyValuesHolder.ofFloat
中的ofFloat
這個方法:
public static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values) {//參數為屬性和屬性值
return new FloatPropertyValuesHolder(property, values);
}
實際上是通過PropertyValuesHolder
的子類FloatPropertyValuesHolder
來保存屬性和屬性值的。
然后我們看點FloatPropertyValuesHolder
的構造方法做了什么事:
public FloatPropertyValuesHolder(Property property, float... values) {
super(property);
setFloatValues(values);
if (property instanceof FloatProperty) {
mFloatProperty = (FloatProperty) mProperty;
}
}
查看下setFloatValues(values);
,如下:
@Override
public void setFloatValues(float... values) {
super.setFloatValues(values);//這里又調用了它父類的setFloatValues() 看這個方法
mFloatKeyframes = (Keyframes.FloatKeyframes) mKeyframes;
}
看下super.setFloatValues(values);
的setFloatValues
這個方法:
//PropertyValuesHolder類
public void setFloatValues(float... values) {
mValueType = float.class;
mKeyframes = KeyframeSet.ofFloat(values);
}
KeyframeSet
意為關鍵幀,設置了關鍵幀后,動畫就可以在各個關鍵幀之間平滑過渡,一個關鍵幀必須包含兩個元素(時間點和位置),即這個關鍵幀是表示的是某個物體在哪個時間點應該在哪個位置上。fraction表示當前位置,value表示當前位置。
總結:ObjectAnimator
通過ofFloat
方法初始化后,內部通過HashMap保存了屬性(key)和屬性值(value),屬性值通過PropertyValuesHolder
保存的,PropertyValuesHolder
是屬性值持有者,它保存了動畫過程中所需要操作的屬性和對應的值,我們通過ofFloat()構造的動畫,ofFloat()的內部實現其實就是將傳進來的參數封裝成PropertyValuesHolder實例化來保存動畫的值,但是實際上是通過PropertyValuesHolder
的子類FloatPropertyValuesHolder
來保存屬性和屬性值的。最終通過設置關鍵幀,動畫就可以在各個關鍵幀之間平滑過渡,一個關鍵幀必須包含兩個元素(時間點和位置),即這個關鍵幀是表示的是某個物體在哪個時間點應該在哪個位置上。