android+3.0新加的动画,Android动画片
使用Android兩年多了,工作中的動(dòng)畫也動(dòng)能應(yīng)付,自認(rèn)為Android中的動(dòng)畫自己也能用個(gè)八九不離十,結(jié)果我在學(xué)習(xí)[Periscope點(diǎn)贊效果](http://www.jianshu.com/p/03fdcfd3ae9c)的時(shí)候發(fā)現(xiàn)動(dòng)畫的這些高級(jí)功能我從沒用過、也沒見過,靜下來仔細(xì)想了下,我也并不明白Android動(dòng)畫的實(shí)現(xiàn)原理,以及生么時(shí)候用什么,從視頻以及ApiDemo中看到的LayoutAnimator以及顏色漸變、類似彈簧的反復(fù)回彈也都沒思路。于是我就研究了下Android的這些動(dòng)畫并記錄了下來。
3.0以前,android支持兩種動(dòng)畫模式,tween animation,frame animation,在3.0中又引入了一個(gè)新的動(dòng)畫系統(tǒng):property animation,這三種動(dòng)畫模式在SDK中被稱為property animation,view animation,drawable animation
1. View Animation(Tween Animation)
View Animation(Tween Animation):補(bǔ)間動(dòng)畫,給出兩個(gè)關(guān)鍵幀,通過一些算法將給定屬性值在給定的時(shí)間內(nèi)在兩個(gè)關(guān)鍵幀間漸變。(xml方式是在anim文件夾中)
a.View Animation只能用于View對(duì)象,而且職能支持一部分功能:位移(translate)、旋轉(zhuǎn)(rotate)、縮放(scale)、透明度漸變(alpha)
b.還有一個(gè)局限性:對(duì)于View Animation,它只是改變了View對(duì)象繪制的位置,而沒有改變View對(duì)象本身(例如:做一個(gè)位移動(dòng)畫,那么可點(diǎn)擊的位置僅僅還是View開始所在的位置,跟移動(dòng)中的這個(gè)動(dòng)畫并無關(guān)系)
c.實(shí)現(xiàn)原理:是父布局不斷的畫出一個(gè)外表一樣的圖像,不斷的通過invalidate 去進(jìn)行重繪,動(dòng)畫的算法其實(shí)都是在Transformation的Matrix矩陣中。
2. Drawable Animation(Frame Animation)
Drawable Animation(Frame Animation):幀動(dòng)畫,就像GIF圖片,通過一系列Drawable依次顯示來模擬動(dòng)畫的效果。(xml方式是在drawable中)
Android中播放GIF圖片的時(shí)候,可使用這種方式(先分解成單個(gè)圖片)。
3. Property Animation
Android 3.0引入,顧名思義,它是實(shí)際更改view的屬性,而不像Tween Animation 僅僅是父布局繪制一個(gè)替身,所以Property Animation的功能會(huì)強(qiáng)大很多。(在包android.animation下)
相同:
Property Animation 兼容了 Tween Animation的所有功能:設(shè)置動(dòng)畫時(shí)間、支持(位移、旋轉(zhuǎn)、縮放、透明度漸變)、類似的監(jiān)聽(開始、結(jié)束、取消、重復(fù))、插補(bǔ)器
加強(qiáng)功能:
后浪推前浪,后出來的Property Animation帶來了更強(qiáng)悍的功能:
1. Evaluators(計(jì)算器):告訴Property Animation系統(tǒng)如何去計(jì)算屬性值
IntEvaluator:用于計(jì)算Int類型屬性值的計(jì)算器。
FloatEvaluator:用于計(jì)算Float類型屬性值的計(jì)算器。
ArgbEvaluator:用于計(jì)算以16進(jìn)制形式表示的顏色值的計(jì)算器。
TypeEvaluator:一個(gè)計(jì)算器接口,它允許你創(chuàng)建你自己的計(jì)算器。如果你正在計(jì)算一個(gè)對(duì)象屬性并不是int,float或者顏色值類型的,那么你必須實(shí)現(xiàn)TypeEvaluator接口去指定如何去計(jì)算對(duì)象的屬性值。
2. 新加了ValueAnimator.AnimatorUpdateListener 監(jiān)聽
onAnimationUpdate() - 在動(dòng)畫的每一幀上調(diào)用. 在這個(gè)方法中,你可以使用ValueAnimator的getAnimatedValue()方法來獲取(Evaluators)計(jì)算出來的值。
AnimationSet提供了一個(gè)把多個(gè)動(dòng)畫組合成一個(gè)組合的機(jī)制,并可設(shè)置組中動(dòng)畫的時(shí)序關(guān)系,如同時(shí)播放,順序播放等。
3. 新增屬性動(dòng)畫的同時(shí),也新增了View的屬性的設(shè)置獲取方法
Example:getLeft、getX、getTranslationX等等
4. 通過AnimationSet應(yīng)用多個(gè)動(dòng)畫
以下例子同時(shí)應(yīng)用5個(gè)動(dòng)畫:
播放anim1;
同時(shí)播放anim2,anim3,anim4;
播放anim5。
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(anim1).before(anim2);
bouncer.play(anim2).with(anim3);
bouncer.play(anim2).with(anim4)
bouncer.play(anim5).after(amin2);
animatorSet.start();
5. ObjectAnimator與ValueAnimator之間的關(guān)系:
其實(shí)ObjectAnimator繼承與ValueAnimator,ObjectAnimator是為了提供簡便的方法,可以直接修改alpha、backgroundColor、translationX、x、y、width等,甚至是一個(gè)普通對(duì)象的屬性,一言以蔽之如果直接通過屬性名改屬性就用ObjectAnimator
例子:Periscope點(diǎn)贊效果實(shí)現(xiàn)
我又換了種方式實(shí)現(xiàn)了下,運(yùn)用我們的屬性動(dòng)畫,直接在ViewGroup上畫出來:
代碼傳送門
6. 同一對(duì)象的多個(gè)屬性同時(shí)變化可優(yōu)化
如果需要對(duì)一個(gè)View的多個(gè)屬性進(jìn)行動(dòng)畫可以用ViewPropertyAnimator類,該類對(duì)多屬性動(dòng)畫進(jìn)行了優(yōu)化,會(huì)合并一些invalidate()來減少刷新視圖,該類在3.1中引入。
以下兩段代碼實(shí)現(xiàn)同樣的效果:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat(“x”, 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat(“y”, 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
myView.animate().x(50f).y(100f);
7. 原理:異步根據(jù)插補(bǔ)器與Evaluator計(jì)算出當(dāng)前View的屬性,再通過handler.post到UI線程,通過反射給View設(shè)置當(dāng)前屬性。
老版本的Property Animation原理講解
Tween Animation 與 Property Animation 使用選擇:
因?yàn)镻roperty Animation最終跟新UI其實(shí)也需要重新繪圖,所以,屬性動(dòng)畫肯定比Tween Animation要更好性能得多,理論上流暢度也稍稍差點(diǎn)。
所以建議能用Tween Animation的地方,還是使用Tween 動(dòng)畫。
根據(jù)ApiDemo羅列了以下幾個(gè)實(shí)用場景(此處會(huì)有不少新的用法):
1. 顏色漸變
private static final int RED = 0xffFF8080;
private static final int BLUE = 0xff8080FF;
ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
2. 布局顯示、不顯示、隱藏(LayoutTransition)
ViewGroup中的子元素可以通過setVisibility使其Visible、Invisible或Gone,當(dāng)有子元素可見性改變時(shí),可以向其應(yīng)用動(dòng)畫,通過LayoutTransition類應(yīng)用此類動(dòng)畫:
transition.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);
通過setAnimator應(yīng)用動(dòng)畫,第一個(gè)參數(shù)表示應(yīng)用的情境,可以以下4種類型:
APPEARING 當(dāng)一個(gè)元素變?yōu)閂isible時(shí)對(duì)其應(yīng)用的動(dòng)畫
CHANGE_APPEARING 當(dāng)一個(gè)元素變?yōu)閂isible時(shí),因系統(tǒng)要重新布局有一些元素需要移動(dòng),這些要移動(dòng)的元素應(yīng)用的動(dòng)畫
DISAPPEARING 當(dāng)一個(gè)元素變?yōu)镮nVisible時(shí)對(duì)其應(yīng)用的動(dòng)畫
CHANGE_DISAPPEARING 當(dāng)一個(gè)元素變?yōu)镚one時(shí),因系統(tǒng)要重新布局有一些元素需要移動(dòng),這些要移動(dòng)的元素應(yīng)用的動(dòng)畫 disappearing from the
container.
步驟:
1. 給view設(shè)置LayoutTransition
LayoutTransition mTransitioner = new LayoutTransition();
view.setLayoutTransition(mTransitioner);
2. 設(shè)置對(duì)應(yīng)時(shí)間
Transitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 500);
3. 設(shè)置動(dòng)畫
ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhRight, pvhScaleX, pvhScaleY).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));
mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);
4. 搞定
3. Keyframes
keyFrame是一個(gè) 時(shí)間/值 對(duì),通過它可以定義一個(gè)在特定時(shí)間的特定狀態(tài),而且在兩個(gè)keyFrame之間可以定義不同的Interpolator,就相當(dāng)多個(gè)動(dòng)畫的拼接,第一個(gè)動(dòng)畫的結(jié)束點(diǎn)是第二個(gè)動(dòng)畫的開始點(diǎn)。KeyFrame是抽象類,要通過ofInt(),ofFloat(),ofObject()獲得適當(dāng)?shù)腒eyFrame,然后通過PropertyValuesHolder.ofKeyframe獲得PropertyValuesHolder對(duì)象
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation =
PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhRight, pvhRotation).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
4. 彈跳
彈跳插補(bǔ)器:bounceAnim.setInterpolator(new BounceInterpolator());
設(shè)置特定一個(gè)時(shí)間點(diǎn),顯示在那幀位置上
bounceAnim.setCurrentPlayTime(seekTime);
5. 反轉(zhuǎn)切換布局
其實(shí)就是一個(gè)旋轉(zhuǎn)動(dòng)畫的拼接,一組對(duì)立的插補(bǔ)器(加速AccelerateInterpolator、減速DecelerateInterpolator)
ObjectAnimator visToInvis = ObjectAnimator.ofFloat(visibleList, "rotationY", 0f, 90f);
visToInvis.setDuration(500);
visToInvis.setInterpolator(accelerator);
final ObjectAnimator invisToVis = ObjectAnimator.ofFloat(invisibleList, "rotationY",
-90f, 0f);
invisToVis.setDuration(500);
invisToVis.setInterpolator(decelerator);
visToInvis.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator anim) {
visibleList.setVisibility(View.GONE);
invisToVis.start();
invisibleList.setVisibility(View.VISIBLE);
}
});
visToInvis.start();
總結(jié)
以上是生活随笔為你收集整理的android+3.0新加的动画,Android动画片的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 零额度信用卡欠年费是怎么回事
- 下一篇: 中签新债破发了怎么办?打新债会不会亏