相比較于ValueAnimator的使用而言,ObjectAnimator才是我們經(jīng)常使用的類(lèi)這里看來(lái)ObjectAnimator像是一個(gè)真正的體力勞動(dòng)者,正如api中的描述一樣ValueAnimator只是為我們提供了一個(gè)數(shù)值變換的能力,同時(shí)也說(shuō)明了ValueAnimator的重要,沒(méi)有它提供這個(gè)數(shù)值的變化,我們的移動(dòng)等也就無(wú)法實(shí)現(xiàn).
由關(guān)系圖我們知道了ObjectAnimator是繼承ValueAnimator的,因此使用起來(lái)也很類(lèi)似,這里完成一個(gè)透明度的變化五秒之內(nèi)從0到1.
private void initAnimator() {
ObjectAnimator animator = ObjectAnimator
.ofFloat(mTv, "alpha", 0f, 1f);
animator.setDuration(5000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
LogUtil.i(animation.getAnimatedValue());
}
});
animator.start();
}
同樣我也監(jiān)聽(tīng)了動(dòng)畫(huà)的執(zhí)行,打印的效果和ValueAnimator是一樣的.這里在調(diào)用工廠類(lèi)獲取對(duì)象的時(shí)候傳遞了四個(gè)參數(shù),最后兩個(gè)很明顯就是起始和終止值,那么前兩個(gè)呢.其實(shí)這里的第一個(gè)參數(shù)就是被作用的TextView對(duì)象,第二個(gè)參數(shù)就是所要的動(dòng)畫(huà)效果,因?yàn)闉榱苏故就该鞫人袀鬟f了
alpha
這個(gè)參數(shù)
常用的屬性值
在系統(tǒng)中為我們準(zhǔn)備好的屬性值有
- alpha 表示view的透明度默認(rèn)是1不透明,0代表完全透明 看不見(jiàn).
- translationX, translationY
- rotation, rotationX, rotationY
- scaleX, scaleY
- pivotX, pivotY
對(duì)任意屬性做動(dòng)畫(huà)
上面的屬性值我們是可以直接使用的,因?yàn)橐陨蠈傩韵到y(tǒng)為我們提供了get,set. 方法也就是說(shuō)屬性動(dòng)畫(huà)要求屬性動(dòng)畫(huà)作用的對(duì)象提供該屬性的get和set方法,屬性動(dòng)畫(huà)根據(jù)外界傳遞的該屬性的初始值和最終值,使用動(dòng)畫(huà)的效果多次去調(diào)用set方法,每次傳遞給set方法的值都不一樣,隨著時(shí)間的推移所傳遞的值越來(lái)越接近最終的值.
因此如果想讓屬性動(dòng)畫(huà)生效,需要滿足下面這兩點(diǎn):
- object必須提供setAbc方法,如果動(dòng)畫(huà)的時(shí)候沒(méi)有傳遞初始值,那么還要提供getAbc方法,因?yàn)橄到y(tǒng)要去取abc屬性的初始值(如果這個(gè)條件不滿足,程序直接crash)
- object的setAbc對(duì)abc所做的改變能夠通過(guò)某種方法反應(yīng)出來(lái),比如帶來(lái)ui的改變之類(lèi)的(這個(gè)條件不滿足,動(dòng)畫(huà)沒(méi)有效果但不會(huì)crash)
解決的方法
- 給你的view對(duì)象加上set和get方法,如果你有權(quán)限的話.
這個(gè)就是說(shuō)如果有權(quán)限直接給view加上set和get方法就好了,但是大多數(shù)情況是我們沒(méi)有這個(gè)權(quán)限,這是android SDK內(nèi)部實(shí)現(xiàn)的.
- 用一個(gè)類(lèi)來(lái)包裝原始對(duì)象,間接為其提供get和set方法
這是一種很有用的方法也很好使用.
public TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = ((TextView) findViewById(R.id.tv));
mTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initAnimator();
}
});
}
private void initAnimator() {
ViewWrapper wrapper = new ViewWrapper(mTv);
ObjectAnimator animator = ObjectAnimator.ofInt(wrapper, "width", 1,500);
animator.setDuration(3000);
// 設(shè)置連續(xù)執(zhí)行
animator.setRepeatCount(-1);
animator.start();
}
private static class ViewWrapper {
private View mTarget;
public ViewWrapper(View target) {
mTarget = target;
}
/**
* 這里處理一個(gè)叫做width的屬性
* 雖然系統(tǒng)里有width這個(gè)屬性,但是實(shí)現(xiàn)的卻不是改變寬度的效果
*
* @param width
*/
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
}
效果如下
- 采用ValueAnimator監(jiān)聽(tīng)動(dòng)畫(huà)過(guò)程,然后自己實(shí)現(xiàn)屬性的改變
我們知道ValueAnimator在start之后在其監(jiān)聽(tīng)時(shí)間中會(huì)有
LogUtil.i(animation.getAnimatedValue());
這個(gè)數(shù)值的連續(xù)改變,因此我們可以在該方法中來(lái)完成ui的改變效果.