摘要:HenCoder Android 自定义 View 1-7:属性动画 Property Animation(进阶篇)
上期的內容,對于大多數簡單的屬性動畫場景已經夠用了。這期的內容主要針對兩個方面:
1. 針對特殊類型的屬性來做屬性動畫;
2. 針對復雜的屬性關系來做屬性動畫。
TypeEvaluator
關于 ObjectAnimator,上期講到可以用 ofInt() 來做整數的屬性動畫和用 ofFloat() 來做小數的屬性動畫。這兩種屬性類型是屬性動畫最常用的兩種,不過在實際的開發中,可以做屬性動畫的類型還是有其他的一些類型。當需要對其他類型來做屬性動畫的時候,就需要用到 TypeEvaluator 了。
ArgbEvaluator
TypeEvaluator 最經典的用法是使用 ArgbEvaluator 來做顏色漸變的動畫。
ObjectAnimator animator = ObjectAnimator.ofInt(view, “color”, 0xffff0000, 0xff00ff00);
animator.setEvaluator(new ArgbEvaluator());
animator.start();
另外,在 Android 5.0 (API 21) 加入了新的方法 ofArgb(),所以如果你的 minSdk 大于或者等于 21(哈哈哈哈哈哈哈哈),
你可以直接用下面這種方式:
ObjectAnimator animator = ObjectAnimator.ofArgb(view, “color”, 0xffff0000, 0xff00ff00);
animator.start();
自定義 Evaluator
如果你對 ArgbEvaluator 的效果不滿意,或者你由于別的什么原因希望寫一個自定義的 TypeEvaluator,你可以這樣寫:
// 自定義 HslEvaluator
private class HsvEvaluator implements TypeEvaluator {
float[] startHsv = new float[3];
float[] endHsv = new float[3];
float[] outHsv = new float[3];
// 使用自定義的 HslEvaluator
animator.setEvaluator(new HsvEvaluator());
animator.start();
ofObject()
借助于 TypeEvaluator,屬性動畫就可以通過 ofObject() 來對不限定類型的屬性做動畫了。方式很簡單:
為目標屬性寫一個自定義的 TypeEvaluator
使用 ofObject() 來創建 Animator,并把自定義的 TypeEvaluator 作為參數填入
private class PointFEvaluator implements TypeEvaluator {
PointF newPoint = new PointF();
}
ObjectAnimator animator = ObjectAnimator.ofObject(view, “position”,
new PointFEvaluator(), new PointF(0, 0), new PointF(1, 1));
animator.start();
另外在 API 21 中,已經自帶了 PointFEvaluator 這個類,所以如果你的 minSdk 大于或者等于 21(哈哈哈哈哈哈哈哈),上面這個類你就不用寫了,直接用就行了。
ofMultiInt() ofMultiFloat()
在 API 引入的新的方法還有 ofMultiInt() 和 ofMultiFloat() 等,用法也很簡單,不過實用性就低了一些。你有興趣的話可以去做一下了解,這里不在多做介紹。
以上這些就是對 TypeEvaluator 的介紹。它的作用是讓你可以對同樣的屬性有不同的解析方式,對本來無法解析的屬性也可以打造出你需要的解析方式。有了 TypeEvaluator,你的屬性動畫就有了更大的靈活性,從而有了無限的可能。
TypeEvaluator 是本期的第一部分內容:針對特殊的屬性來做屬性動畫,它可以讓你「做到本來做不到的動畫」。接下來是本期的第二部分內容:針對復雜的屬性關系來做動畫,它可以讓你「能做到的動畫做起來更簡單」。
PropertyValuesHolder 同一個動畫中改變多個屬性
很多時候,你在同一個動畫中會需要改變多個屬性,例如在改變透明度的同時改變尺寸。如果使用 ViewPropertyAnimator,你可以直接用連寫的方式來在一個動畫中同時改變多個屬性:
view.animate()
.scaleX(1)
.scaleY(1)
.alpha(1);
而對于 ObjectAnimator,是不能這么用的。不過你可以使用 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 分別執行了。
AnimatorSet 多個動畫配合執行
有的時候,你不止需要在一個動畫中改變多個屬性,還會需要多個動畫配合工作,比如,在內容的大小從 0 放大到 100% 大小后開始移動。這種情況使用 PropertyValuesHolder 是不行的,因為這些屬性如果放在同一個動畫中,需要共享動畫的開始時間、結束時間、Interpolator 等等一系列的設定,這樣就不能有先后次序地執行動畫了。
這就需要用到 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 進行統一規劃和管理,讓它們按照要求的順序來工作。
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();
第二部分,「關于復雜的屬性關系來做動畫」,就這么三種:
1. 使用 PropertyValuesHolder 來對多個屬性同時做動畫;
2. 使用 AnimatorSet 來同時管理調配多個動畫;
3. PropertyValuesHolder 的進階使用:使用 PropertyValuesHolder.ofKeyframe() 來把一個屬性拆分成多段,執行更加精細的屬性動畫。
ValueAnimator 最基本的輪子
額外簡單說一下 ValuesAnimator。很多時候,你用不到它,只是在你使用一些第三方庫的控件,而你想要做動畫的屬性卻沒有 setter / getter 方法的時候,會需要用到它。
除了 ViewPropertyAnimator 和 ObjectAnimator,還有第三個選擇是 ValueAnimator。ValueAnimator 并不常用,因為它的功能太基礎了。ValueAnimator 是 ObjectAnimator 的父類,實際上,ValueAnimator 就是一個不能指定目標對象版本的 ObjectAnimator。ObjectAnimator 是自動調用目標對象的 setter 方法來更新目標屬性的值,以及很多的時候還會以此來改變目標對象的 UI,而 ValueAnimator 只是通過漸變的方式來改變一個獨立的數據,這個數據不是屬于某個對象的,至于在數據更新后要做什么事,全都由你來定,你可以依然是去調用某個對象的 setter 方法(別這么為難自己),也可以做其他的事,不管要做什么,都是要你自己來寫的,ValueAnimator 不會幫你做。功能最少、最不方便,但有時也是束縛最少、最靈活。比如有的時候,你要給一個第三方控件做動畫,你需要更新的那個屬性沒有 setter 方法,只能直接修改,這樣的話 ObjectAnimator 就不靈了啊。怎么辦?這個時候你就可以用 ValueAnimator,在它的 onUpdate() 里面更新這個屬性的值,并且手動調用 invalidate()。
所以你看,ViewPropertyAnimator、ObjectAnimator、ValueAnimator 這三種 Animator,它們其實是一種遞進的關系:從左到右依次變得更加難用,也更加靈活。但我要說明一下,它們的性能是一樣的,因為 ViewPropertyAnimator 和 ObjectAnimator 的內部實現其實都是 ValueAnimator,ObjectAnimator 更是本來就是 ValueAnimator 的子類,它們三個的性能并沒有差別。它們的差別只是使用的便捷性以及功能的靈活性。所以在實際使用時候的選擇,只要遵循一個原則就行:盡量用簡單的。能用 View.animate() 實現就不用 ObjectAnimator,能用 ObjectAnimator 就不用 ValueAnimator。
總結
以上是生活随笔為你收集整理的摘要:HenCoder Android 自定义 View 1-7:属性动画 Property Animation(进阶篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈Junit4和TestNG中的参数化
- 下一篇: centos 宝塔面板 mongodb