动画七、动画的PropertyValuesHolder与Keyframe
本學習筆記主要來自啟艦:
http://blog.csdn.net/harvic880925/article/details/50752838
在學習過程中融入了自己的理解和思路。
前面掌握了ValueAnimator、ObjectAnimator動畫通過通過ofInt(), ofFloat(), ofObject()等方式創建實例,實際上動畫實例的創建還有另外的方法:
//valueAnimator的 public ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values){} // ObjectAnimator的 public ObjectAnimator ofPropertyValuesHolder(Object target,PropValueHolder... values){}也就是說ValueAnimator和ObjectAnimator除了通過ofInt(), ofFloat(), ofObject()創建實例外,還都有一個ofPropertyValuesHolder()方法來創建實例,這篇文章我就帶大家來看看如何通過ofPropertyValuesHolder()來創建實例的。
由于ValueAnimator和ObjectAnimator都具有ofPropertyValuesHolder()函數,使用方法也差不多,相比而言,ValueAnimator的使用機會不多,這里我們就只講ObjectAnimator中ofPropertyValuesHolder()的用法。相信大家懂了這篇以后,再去看ValueAnimator的ofPropertyValuesHolder(),也應該是會用的。
一、PropertyValuesHolder
1、概述
PropertyValuesHolder的意義是:它其中保存了動畫過程中所需要操作的屬性和對應的值。我們通過ofFloat(Object target, String propertyName, float… values)構造的動畫,ofFloat()的內部實現其實就是將傳進來的參數封裝成PropertyValuesHolder實例來保存動畫狀態。在封裝成PropertyValuesHolder實例以后,后期的各種操作也是以PropertyValuesHolder為主。
PropertyValuesHolder中有很多函數,有些函數的api等級是11,有些函數的api等級是14和21; 高api的函數我們就不講了,只講講api 11的函數的用法。
首先,我們來看看創建實例的函數:
public PropertyValuesHolder ofFloat(String propertyName, float... values){} public PropertyValuesHolder ofInt(String propertyName, int... values){} public PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values){} public PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values){}這一段我們著重講ofFloat、ofInt和ofObject的用法,ofKeyframe我們單獨講。
2、PropertyValuesHolder之ofFloat()、ofInt()
(1)ofFloat()、ofInt():
我們先來看看它們的構造函數:
propertyName:表示ObjectAnimator需要操作的屬性名。即ObjectAnimator需要通過反射查找對應屬性的setProperty()函數的那個property.
values:屬性所對應的參數,同樣是可變長參數,可以指定多個,還記得我們在ObjectAnimator中講過,如果只指定了一個,那么ObjectAnimator會通過查找getProperty()方法來獲得初始值。
(2)、ObjectAnimator.ofPropertyValuesHolder()
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values){}target:指需要執行動畫的控件;
values:是一個可變長參數,可以傳進去多個PropertyValuesHolder實例,由于每個PropertyValuesHolder實例都會針對一個屬性做動畫,所以如果傳進去多個PropertyValuesHolder實例,將會對控件的多個屬性同時做動畫操作。
下面我們就舉個例子來說明如何通過PropertyValuesHolder的ofFloat、ofInt來做動畫。
private void doPropertyAnimator() {PropertyValuesHolder holder = PropertyValuesHolder.ofFloat("Rotation",60f, -60f, 50f, -50f, -40f, 40f, 30f, -30f, 20f, -20f, 10f, -10f, 0f);PropertyValuesHolder holderColor = PropertyValuesHolder.ofInt("BackgroundColor", 0xfffffff0, 0xffff00ff, 0xffffff00, 0xffffff0f);objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mFlAnimator, holder, holderColor);objectAnimator.setDuration(500);objectAnimator.setRepeatMode(ValueAnimator.REVERSE);objectAnimator.setRepeatCount(ValueAnimator.INFINITE);objectAnimator.setInterpolator(new LinearInterpolator());objectAnimator.start(); }其中,mFlAnimator是自定義TextView(ObjTextView)在xml中的布局,ObjTextView如下:
public class ObjTextView extends TextView {public ObjTextView(Context context, AttributeSet attrs) {super(context, attrs);}public void setCharText(Character character){setText(String.valueOf(character));} }Holder對象設定了動畫旋轉的角度,holderColor對象設定了動畫的背景色變化,objectAnimator動畫對象里面添加了target控件對象及可變參數Holder和holderColor,當然我們還可以在這里添加別的參數,比如透明度(alpha)的變化,縮放(scale)等動畫效果。
3、PropertyValuesHolder之ofObject()
(1)、概述
我們先來看一下ofObject的構造函數:
參數的含義,再次不多說,不懂的話就找根面條上吊得了。
(2)、示例
這段代碼簡單,前面也已經講解過很多次了,不多說,不懂的話就找根面條上吊得了。
public class ObjTextView extends TextView {public ObjTextView(Context context, AttributeSet attrs) {super(context, attrs);}public void setCharText(Character character){setText(String.valueOf(character));} }從CharEvaluator中可以看出,從CharEvaluator中產出的動畫中間值類型為Character類型。TextView中雖然有setText(CharSequence text) 函數,但這個函數的參數類型是CharSequence,而不是Character類型。所以我們要自定義一個類派生自TextView來改變TextView的字符:
public class ObjTextView extends TextView {public ObjTextView(Context context, AttributeSet attrs) {super(context, attrs);}public void setCharText(Character character){setText(String.valueOf(character));} }這個與之前上面的相同。
動畫的代碼如下:
private void doPropertyObjAnimator() {PropertyValuesHolder holderText = PropertyValuesHolder.ofObject("CharText", new CharEvaluator(), new Character('A'), new Character('Z'));PropertyValuesHolder holder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 50f, -50f, -40f, 40f, 30f, -30f, 20f, -20f, 10f, -10f, 0f);PropertyValuesHolder holderColor = PropertyValuesHolder.ofInt("BackgroundColor", 0xfffffff0, 0xffff00ff, 0xffffff00, 0xffffff0f);objectAnimator01 = ObjectAnimator.ofPropertyValuesHolder(mFlAnimator, holderText, holder, holderColor);objectAnimator01.setDuration(2000);objectAnimator01.setInterpolator(new LinearInterpolator());objectAnimator01.setRepeatCount(ValueAnimator.INFINITE);objectAnimator01.setRepeatMode(ValueAnimator.REVERSE);objectAnimator01.start(); }首先是根據PropertyValuesHolder.ofObject生成一個PropertyValuesHolder實例,注意它的屬性就是CharText,所對應的set函數就是setCharText,由于CharEvaluator的中間值是Character類型,所以CharText屬性所對應的完整的函數聲明為setCharText(Character character);這也就是我們為什么要自定義一個MyTextView原因,就是因為TextView中沒有setText(Character character)這樣的函數。
二、Keyframe
1、概述:KeyFrame直譯過來就是關鍵幀。 一個關鍵幀必須包含兩個原素,第一時間點,第二位置。即這個關鍵幀是表示的是某個物體在哪個時間點應該在哪個位置上。
KeyFrame的生成方式為:
Keyframe kf0 = Keyframe.ofFloat(0, 0); Keyframe kf1 = Keyframe.ofFloat(0.1f, -20f); Keyframe kf2 = Keyframe.ofFloat(1f, 0);上面生成了三個KeyFrame對象,其中KeyFrame的ofInt函數的聲明為:
public static Keyframe ofFloat(float fraction, float value);fraction:表示當前的顯示進度,即從加速器中getInterpolation()函數的返回值;
value:表示當前應該在的位置
比如Keyframe.ofFloat(0, 0)表示動畫進度為0時,動畫所在的數值位置為0;Keyframe.ofFloat(0.25f, -20f)表示動畫進度為25%時,動畫所在的數值位置為-20;Keyframe.ofFloat(1f,0)表示動畫結束時,動畫所在的數值位置為0;
在理解了KeyFrame.ofFloat()的參數以后,我們來看看PropertyValuesHolder是如何使用KeyFrame對象的:
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values);fraction:表示當前的顯示進度,即從加速器中getInterpolation()函數的返回值;
value:表示當前應該在的位置
2、示例:
private void doOfFloatAnim(){Keyframe frame0 = Keyframe.ofFloat(0f, 0);Keyframe frame1= Keyframe.ofFloat(0.1f, -20f);Keyframe frame2 = Keyframe.ofFloat(0.2f, 20f);Keyframe frame3 = Keyframe.ofFloat(0.3f, -20f);Keyframe frame4 = Keyframe.ofFloat(0.4f, 20f);Keyframe frame5 = Keyframe.ofFloat(0.5f, -20f);Keyframe frame6 = Keyframe.ofFloat(0.6f, 20f);Keyframe frame7 = Keyframe.ofFloat(0.7f, -20f);Keyframe frame8 = Keyframe.ofFloat(0.8f, 20f);Keyframe frame9 = Keyframe.ofFloat(0.9f, -20f);Keyframe frame10 = Keyframe.ofFloat(1, 0);frameHolder = PropertyValuesHolder.ofKeyframe("rotation", frame0, frame1, frame2, frame3, frame4, frame5, frame6, frame7, frame8, frame9, frame10);frameHolder.setEvaluator(new CharEvaluator());animator = ObjectAnimator.ofPropertyValuesHolder(mIvKeyframe, frameHolder);animator.setDuration(500);animator.setInterpolator(new LinearInterpolator());animator.start(); }3、Keyframe之ofFloat、ofInt與常用函數
(1)、ofFloat、ofInt
其實Keyframe除了ofFloat()以外,還有ofInt()、ofObject()這些創建Keyframe實例的方法,Keyframe.ofObject()我們下部分再講,這部分,我們著重看看ofFloat與ofInt的構造函數與使用方法:
2)、常用函數:
//設置fraction參數,即Keyframe所對應的進度; public void setFraction(float fraction) // 設置當前Keyframe所對應的值; public void setValue(Object value) // 設置Keyframe動作期間插值器; public void setInterpolator(TimeInterpolator interpolator)這三個函數中,插值器的作用應該是比較難理解,如果給這個Keyframe設置上插值器,那么這個插值器就是從上一個Keyframe開始到當前設置插值器的Keyframe時,這個過程值的計算是利用這個插值器的,比如:
Keyframe frame0 = Keyframe.ofFloat(0f, 0); Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f); frame1.setInterpolator(new BounceInterpolator()); Keyframe frame2 = Keyframe.ofFloat(1f, 20f); frame2.setInterpolator(new LinearInterpolator());在上面的代碼中,我們給frame1設置了插值器BounceInterpolator,那么在frame0到frame1的中間值計算過程中,就是用的就是回彈插值器;
同樣,我們給frame2設置了線性插值器(LinearInterpolator),所以在frame1到frame2的中間值計算過程中,使用的就是線性插值器。很顯然,給Keyframe.ofFloat(0f, 0)設置插值器是無效的,因為它是第一幀。
4、Keyframe之ofObject
與ofInt,ofFloat一樣,ofObject也有兩個構造函數:
同樣,如果使用ofObject(float fraction)來構造,也必須使用setValue(Object value)來設置這個關鍵幀所對應的值。我們還以TextView更改字母的例子來使用下Keyframe.ofObject.
private void doKeyframeofObject(){Keyframe frame0 = Keyframe.ofObject(0f, new Character('A'));Keyframe frame1 = Keyframe.ofObject(0.1f, new Character('L'));Keyframe frame2 = Keyframe.ofObject(1,new Character('Z'));frameHolder02 = PropertyValuesHolder.ofKeyframe("CharText",frame0,frame1,frame2);frameHolder02.setEvaluator(new CharEvaluator());animator02 = ObjectAnimator.ofPropertyValuesHolder(mFlAnimator, frameHolder);animator02.setDuration(3000);animator02.start(); }利用關鍵幀創建PropertyValuesHolder后,一定要記得設置自定義的Evaluator:
frameHolder02.setEvaluator(new CharEvaluator());凡是使用ofObject來做動畫的時候,都必須調用frameHolder.setEvaluator顯示設置Evaluator,因為系統根本是無法知道,你動畫的中間值Object真正是什么類型的。
如果去掉第0幀,將以第一個關鍵幀為起始位置
如果去掉結束幀,將以最后一個關鍵幀為結束位置
使用Keyframe來構建動畫,至少要有兩個或兩個以上幀
三、PropertyValuesHolder的其它函數
// 設置動畫的Evaluator public void setEvaluator(TypeEvaluator evaluator);// 用于設置ofFloat所對應的動畫值列表 public void setFloatValues(float... values);// 用于設置ofInt所對應的動畫值列表 public void setIntValues(int... values);// 用于設置ofKeyframe所對應的動畫值列表 public void setKeyframes(Keyframe... values);// 用于設置ofObject所對應的動畫值列表 public void setObjectValues(Object... values);// 設置動畫屬性名 public void setPropertyName(String propertyName);這些函數都比較好理解。
如果是利用PropertyValuesHolder.ofObject()來創建動畫實例的話,我們是一定要顯示調用 PropertyValuesHolder.setEvaluator()來設置Evaluator的。謹記!謹記!!謹記!!!
總結
以上是生活随笔為你收集整理的动画七、动画的PropertyValuesHolder与Keyframe的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10更新(windows upda
- 下一篇: 【人工智能】发展简史 | 复习笔记