屬性動(dòng)畫(huà)中最基礎(chǔ)的 ObjectAnimator
ObjectAnimator
是屬性動(dòng)畫(huà)中最重要的實(shí)行類(lèi),創(chuàng)建一個(gè)ObjectAnimator
只需要通過(guò)他的靜態(tài)工廠方類(lèi)直接返回一個(gè)ObjectAnimator
對(duì)象余爆。參數(shù)包括一個(gè)對(duì)象和對(duì)象的屬性名字寇窑,但這個(gè)屬性必須有get
和set
函數(shù)却桶,內(nèi)部會(huì)通過(guò)反射機(jī)制來(lái)調(diào)用set函數(shù)修改對(duì)象屬性值,也可以調(diào)用setInterpolator
設(shè)置對(duì)應(yīng)的差值器。
屬性動(dòng)畫(huà)操作的是屬性阶女,所以被操作的view可以響應(yīng)事件颊糜。
例子:實(shí)現(xiàn)平移動(dòng)畫(huà)
ObjectAnimator animator = ObjectAnimator.ofFloat(
view,
"translationX",
300
);
animator.setDuration(300);
animator.start();
- 第一個(gè)參數(shù)是要操縱的
View
- 第二個(gè)參數(shù)是要操作的屬性
- 第三個(gè)是一個(gè)可變數(shù)組參數(shù),需要穿進(jìn)去該屬性變化的一個(gè)取值過(guò)程秃踩,這里就是變化到300
- 下面是給動(dòng)畫(huà)設(shè)置時(shí)長(zhǎng)衬鱼,差值器等屬性
注意到ofFloat
方法,這是源碼中的注釋
/**
* Constructs and returns an ObjectAnimator that animates between float values. A single
* value implies that that value is the one being animated to. Two values imply starting
* and ending values. More than two values imply a starting value, values to animate through
* along the way, and an ending value (these values will be distributed evenly across
* the duration of the animation).
*
* @param target The object whose property is to be animated. This object should
* have a public method on it called <code>setName()</code>, where <code>name</code> is
* the value of the <code>propertyName</code> parameter.
* @param propertyName The name of the property being animated.
* @param values A set of values that the animation will animate between over time.
* @return An ObjectAnimator object that is set up to animate between the given values.
*/
大概意思是:
/**
* 構(gòu)造并返回一個(gè)浮點(diǎn)值之間的動(dòng)畫(huà)ObjectAnimator憔杨。單
* 值意味著該值被動(dòng)畫(huà)的之一鸟赫。兩個(gè)值意味著啟動(dòng)
* 和結(jié)束值。多于兩個(gè)值意味著一個(gè)起始值芍秆,值動(dòng)畫(huà)通過(guò)
* 一路走來(lái)惯疙,和結(jié)束值(這些值將均勻分布在整個(gè)
* 動(dòng)畫(huà)的持續(xù)時(shí)間)。
*
* @參數(shù)target其屬性是動(dòng)畫(huà)的對(duì)象妖啥。這個(gè)對(duì)象應(yīng)該
* 有它的公共方法叫做<代碼>的setName()</代碼>霉颠,其中<代碼>名稱(chēng)</ code>的是
* 在<code>的值propertyname</ code>的參數(shù)。
* @參數(shù)PROPERTYNAME被動(dòng)畫(huà)的屬性的名稱(chēng)荆虱。
* @參數(shù)值一組動(dòng)畫(huà)將隨著時(shí)間的推移之間的動(dòng)畫(huà)值蒿偎。
* 返回:已設(shè)置給定的值之間設(shè)置動(dòng)畫(huà)的ObjectAnimator對(duì)象。
*/
在使用ObjectAnimator
的時(shí)候要注意的就是屬性必須有get
和set
方法怀读,否則ObjectAnimator
就無(wú)法生效诉位。下面是常用的可以直接使用屬性動(dòng)畫(huà)的屬性值:
-
translationX
和translationY
:這兩個(gè)屬性作為一種增量來(lái)控制著View
對(duì)象從它布局容器左上角坐標(biāo)偏移的位置。 -
rotation,rotationX,rotationY
:這三個(gè)屬性控制View對(duì)象圍繞支點(diǎn)進(jìn)行2D和3D旋轉(zhuǎn)菜枷。 -
scaleX,scaleY
:這兩個(gè)屬性控制View
對(duì)象圍繞它的支點(diǎn)進(jìn)行2D縮放苍糠。 -
pivotX,pivotY
:這兩個(gè)屬性控制著View
對(duì)象的支點(diǎn)位置,圍繞這個(gè)支點(diǎn)進(jìn)行旋轉(zhuǎn)和縮放變換處理啤誊。默認(rèn)情況下岳瞭,支點(diǎn)是View
對(duì)象的中心點(diǎn)。 -
x
和y
:這是兩個(gè)簡(jiǎn)單實(shí)用的屬性蚊锹,它描述了View對(duì)象在它容器中的最終位置瞳筏,它是最初左上角坐標(biāo)和translationX、translationY
值的累計(jì)和牡昆。 -
alpha
:它表示View
對(duì)象的alpha
透明度姚炕。默認(rèn)是1(不透明),0代表完全透明(不可見(jiàn))
如果一個(gè)屬性沒(méi)有有get
和set
方法丢烘,有兩種解決方法柱宦。
- 通過(guò)自定義一個(gè)屬性類(lèi)或包裝類(lèi)來(lái)間接給這個(gè)屬性添加
get、set
方法播瞳。 - 通過(guò)ValueAnimator實(shí)現(xiàn)
第一種捷沸,通過(guò)自定義一個(gè)屬性類(lèi)或包裝類(lèi)來(lái)間接給這個(gè)屬性添加get、set
方法:
WrapperView wrapper = new WrapperView(view);
ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
private static class WrapperView {
private View mTarget;
public WrapperView(View mTarget) {
this.mTarget = mTarget;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
PropertyValuesHolder
如果針對(duì)同一個(gè)對(duì)象的多個(gè)屬性狐史,要同時(shí)作用多種動(dòng)畫(huà)痒给,可以使用PropertyValuesHolder
來(lái)實(shí)現(xiàn)说墨,比如在平移中,同時(shí)改變X苍柏、Y
軸的縮放尼斧,可以這樣實(shí)現(xiàn):
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300f);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3).setDuration(1000).start();
ValueAnimator
ValueAnimator
本身不提供任何動(dòng)畫(huà)效果,它更像一個(gè)數(shù)值發(fā)生器试吁,用來(lái)產(chǎn)生具有一定規(guī)律的數(shù)字棺棵。從而讓調(diào)用者控制動(dòng)畫(huà)的實(shí)現(xiàn)過(guò)程,ValueAnimator
的一般使用方法如下:
ValueAnimator animator = ValueAnimator.ofFloat(0, 100);
animator.setTarget(view);
animator.setDuration(5000).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Float value = (Float) animation.getAnimatedValue();
//TODO use the value
Log.i("MainActivity", "value = " + value);
}
});
其中AnimatorUpdateListener
監(jiān)聽(tīng)數(shù)值的變換熄捍,從而完成動(dòng)畫(huà)的變換烛恤,這個(gè)例子中,value輸出的是從0到100
動(dòng)畫(huà)事件監(jiān)聽(tīng)
一個(gè)完整的動(dòng)畫(huà)監(jiān)聽(tīng)包括四個(gè)過(guò)程:
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0.5f);
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
但是大部分時(shí)候余耽,我們只關(guān)心onAnimationEnd
事件缚柏,所以還可以這樣通過(guò)AnimatorListenerAdapter
選擇想要的事件進(jìn)行監(jiān)聽(tīng):
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
AnimatorSet
對(duì)于一個(gè)屬性同時(shí)作用多個(gè)屬性動(dòng)畫(huà)效果,除了使用PropertyValuesHolder
外碟贾,還可以使用AnimatorSet
,而且AnimatorSet
還可以實(shí)現(xiàn)更為精確的順序控制币喧。
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0, 1f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0, 1f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(animator1, animator2, animator3);
set.start();
在屬性動(dòng)畫(huà)中,AnimatorSet
通過(guò)playTogether();playSequentially();set.play().with();set.play().before();set.play().after();
這些方法來(lái)控制多個(gè)動(dòng)畫(huà)的協(xié)同工作方式袱耽,從而做到對(duì)動(dòng)畫(huà)播放順序的精確控制杀餐。