最近年末了,打算把本身的Android知識都整理一下。html
Android技能書系列:java
Android基礎知識android
Android技能樹 — View小結github
Android技能樹 — View事件體系小結canvas
Android技能樹 — Android存儲路徑及IO操做小結數組
數據結構基礎知識
算法基礎知識
最近整理了下本身學過的動畫方面的知識。用百度腦圖作了動畫知識的思惟腦圖,哪裏若是以爲不對,你們能夠留言提出哦。
你沒看錯,掘金的文章的圖片,電腦上看這種思惟腦圖根本就看不清楚,因此我準備一塊塊來說。 (掘金手機版APP卻是能夠放大,看的挺清晰的。)
總結的圖已經傳到了Github上面,能夠下載:
動畫能夠分爲兩類:Animation 和 Transition二類。
由於通常來講第二塊Animation用的比較多,因此咱們先來看Animation這塊:
好的,咱們能夠看到咱們的Animation能夠分紅:
咱們能夠按順序一個個來看:
咱們能夠看到,其實View動畫很簡單,基本使用的是「平移」,「縮放」,「旋轉」,「透明度」四種基本動畫。
而後咱們看特殊場景下的View動畫:
好比:
這裏的界面切換動畫,與最剛開始的大分類的Transition不一樣,這裏的過渡的動畫用的是View動畫,好比Activity的切換效果:
//當啓動一個Activity時
Intent intent = new Intent(this,XXXXX.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
//當Activity退出時
@Override
public void finish(){
super.finish();
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
}
複製代碼
其中咱們能夠看到主要是用到overridePendingTransition
方法,這個方法必須放在startActivity()
和finish()
後面。
也許有人會問,那若是我就是但願按鈕移動到右邊後,點擊右邊的按鈕能夠有點擊事件,你能夠選擇後面提到的屬性動畫,或者若是你必定要用View動畫,那你能夠在右邊目標位置,提早準備一個如出一轍的而且隱藏的按鈕,而後當左邊的按鈕移動到右邊後,咱們能夠設置右邊的隱藏的按鈕出現,而後把左邊的最初的按鈕進行隱藏便可。
首先你們能夠看下扔物線大佬的相關這個知識點的文章:
HenCoder Android 自定義 View 1-6: 屬性動畫(上手篇)
【HenCoder Android 開發進階】自定義 View 1-7:屬性動畫(進階篇)
我直接引用了扔物線大佬文章裏面的相關動畫操做的圖片:
用ViewPropertyAnimator 來作屬性動畫是最簡單的。特別方便。
若是想多個動畫同時進行,只須要簡單的:
view.animate()
.scaleX(1)
.scaleY(1)
.alpha(1);
複製代碼
引用扔物線大佬裏面的內容:
public class SportsView extends View {
float progress = 0;
......
// 建立 getter 方法
public float getProgress() {
return progress;
}
// 建立 setter 方法
public void setProgress(float progress) {
this.progress = progress;
invalidate();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
......
canvas.drawArc(arcRectF, 135, progress * 2.7f, false, paint);
......
}
}
......
// 建立 ObjectAnimator 對象
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "progress", 0, 65);
// 執行動畫
animator.start();
複製代碼
ObjectAnimation在多個動畫一塊兒進行的時候不能像ViewPropertyAnimation那樣方便,不過你可使用 PropertyValuesHolder 來同時在一個動畫中改變多個屬性:
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 1);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 1);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("alpha", 1);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, holder1, holder2, holder3)
animator.start();
複製代碼
PropertyValuesHolder
的意思從名字能夠看出來,它是一個屬性值的批量存放地。因此你若是有多個屬性須要修改,能夠把它們放在不一樣的 PropertyValuesHolder
中,而後使用 ofPropertyValuesHolder()
統一放進 Animator
。這樣你就不用爲每一個屬性單首創建一個Animator
分別執行了。
PropertyValuesHolders.ofKeyframe()
把同一個屬性拆分 除了合併多個屬性和調配多個動畫,你還能夠在 PropertyValuesHolder
的基礎上更進一步,經過設置 Keyframe
(關鍵幀),把同一個動畫屬性拆分紅多個階段。
例如,你可讓一個進度增長到 100% 後再「反彈」回來。
// 在 0% 處開始
Keyframe keyframe1 = Keyframe.ofFloat(0, 0);
// 時間通過 50% 的時候,動畫完成度 100%
Keyframe keyframe2 = Keyframe.ofFloat(0.5f, 100);
// 時間見過 100% 的時候,動畫完成度倒退到 80%,即反彈 20%
Keyframe keyframe3 = Keyframe.ofFloat(1, 80);
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("progress", keyframe1, keyframe2, keyframe3);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, holder);
animator.start();
複製代碼
ValueAnimator valueAnimator = ValueAnimator.ofInt(1,5);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();//當前的值
}
});
複製代碼
咱們能夠看到ValueAnimator是監聽到當前變化到哪一個值了。而後你拿着這個值想怎麼處理,就是你的事了。因此ValueAnimator就更基礎。
因此你看,ViewPropertyAnimator、ObjectAnimator、ValueAnimator 這三種 Animator,它們實際上是一種遞進的關係:從左到右依次變得更加難用,也更加靈活。但我要說明一下,它們的性能是同樣的,由於 ViewPropertyAnimator 和 ObjectAnimator 的內部實現其實都是 ValueAnimator,ObjectAnimator 更是原本就是 ValueAnimator 的子類,它們三個的性能並無差異。它們的差異只是使用的便捷性以及功能的靈活性。因此在實際使用時候的選擇,只要遵循一個原則就行:儘可能用簡單的。能用 View.animator() 實現就不用 ObjectAnimator,能用 ObjectAnimator 就不用 ValueAnimator。
AnimationSet爲何要把這個單獨拎出來呢。AnimationSet能夠用在多個動畫播放,不少人就說了,上面咱們在ViewPropertyAnimator 及ObjectAnimation中的PropertyValuesHolder已經能夠用在多個動畫一塊兒播放了嗎?沒錯,問題就出在這個<一塊兒>這二個字上面,由於上面的二個都是隻能N個動畫同時播放,好比我如今的需求是先平移,而後平移結束後再放大和改變透明度。而AnimationSet及能夠一塊兒播放,又能夠控制動畫的前後順序來。
ObjectAnimator animator1 = ObjectAnimator.ofFloat(...);
animator1.setInterpolator(new LinearInterpolator());
ObjectAnimator animator2 = ObjectAnimator.ofInt(...);
animator2.setInterpolator(new DecelerateInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
// 兩個動畫依次執行
animatorSet.playSequentially(animator1, animator2);
animatorSet.start();
複製代碼
使用 playSequentially(),就可讓兩個動畫依次播放,而不用爲它們設置監聽器來手動爲他們監管協做。 AnimatorSet 還能夠這麼用:
// 兩個動畫同時執行
animatorSet.playTogether(animator1, animator2);
animatorSet.start();以及這麼用:
// 使用 AnimatorSet.play(animatorA).with/before/after(animatorB)
// 的方式來精確配置各個 Animator 之間的關係
animatorSet.play(animator1).with(animator2);
animatorSet.play(animator1).before(animator2);
animatorSet.play(animator1).after(animator2);
animatorSet.start();
複製代碼
有了 AnimatorSet ,你就能夠對多個 Animator 進行統一規劃和管理,讓它們按照要求的順序來工做。
插值器(Interpolator)和 估值器(Evaluator)你們確定也見過不少次,那這二個究竟是用來幹嗎的呢?
咱們從頭來分析一個平移的動畫:
translationX
的屬性,讓View去移動。那咱們的插值器和估值器是用在哪裏呢:
插值器是用在第二步裏面,時間經歷了N秒,咱們返回一個值,這個值是說明當前動畫進行到哪一個程度了。
估值器是用在第三步,咱們已經知道了動畫執行到了哪一個程序,而後咱們返回具體的當前變化的數值。
好比咱們來看LinearInterpolator.java
和IntEvaluator.java
的原來再理解下:
public class LinearInterpolator implements Interpolator{
public LinearInterpolator(){
}
public LinearInterpolator(Context context,AttributeSet attrs){
}
public float getInterpolation(float input){
//好比時間是5秒,這時候過了2.5秒,這時候時間流逝了0.5,因此input是0.5
//由於咱們這個LiearInterpolator是線性插值器,
//因此時間流失了0.5,咱們的動畫的動畫也執行了0.5(也就是完成了50%的程度)
//因此這裏直接返回input便可。
return input;
}
}
複製代碼
public class IntEvaluator implements TypeEvaluator<Integer>{
public Integer evaluate(float fraction,Integer startValue,Integer endValue){
//fraction就是咱們上面插值器返回的,告訴咱們動畫執行到什麼程度了。
//startValue是咱們起始值,endValue是咱們最後的目標值。
//好比咱們是ofInt(0,500);這時候咱們return的值就是(0+0.5 * (500-0))= 250
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startValue));
}
}
複製代碼
過於過渡,我也不費心思所有很詳細的寫出來,網上的基本介紹及使用有不少。
Android 過渡(Transition)動畫解析之基礎篇
Activity和Fragment Transition介紹
深刻理解共享元素變換(Shared Element Transition)-上