屬性動畫,這個是在Android 3.0中才引進的。Property Animation故名思議就是通過動畫的方式改變對象的屬性.屬性動畫更改的是對象的實際屬性,在View Animation(Tween Animation)中,其改變的是View的繪製效果,真正的View的屬性保持不變。可以將屬性動畫理解爲增強版的補間動畫。
比如無論如何縮放Button的大小,Button的有效點擊區域還是沒有應用動畫時的區域,其位置與大小都不變。而在Property Animation中,改變的是對象的實際屬性,如Button的縮放,Button的位置與大小屬性值都改變了。
Property Animation不止可以應用於View,還可以應用於任何對象。Property Animation只是表示一個值在一段時間內的改變,當值改變時要做什麼事情完全是你自己決定的。
(二)爲什麼引入屬性動畫
Android3.0之前提供的補間動畫機制還算相對比較健全的,比如你的需求中只需要對View進行移動、縮放、旋轉和淡入淡出的操作,那麼補間動畫已經足夠健全了。但是,如果一旦需求超出了這四種操作,補間動畫就無能爲力了。
例如,我們需要改變View的寬度,這個時候就不能通過補間動畫實現。此外,補間動畫還有一個最大的缺陷,就是它只是改變了View的顯示效果而已,並不會真正的改變View的屬性。具體來說,例如屏幕左上角有一個Button,使用補間動畫將其移動到右下角,此刻你去點擊右下角的Button,它是絕對不會響應點擊事件的,因此其作用區域依然還在左上角。只不過是補間動畫將其繪製在右下角而已。
(三)、屬性動畫常用屬性:
Duration動畫的持續時間,默認300ms。android:duration屬性(對應的xml文件)
Time interpolation:時間插值。LinearInterpolator、AccelerateDecelerateInterpolator,定義動畫的變化率。android:interpolator屬性
Repeat count and behavior:重複次數、以及重複模式;可以定義重複多少次;重複時從頭開始(restart),還是反向(reverse)。android:repeatCount屬性(可以是整數也可以是infinite(無限))android:repeatMode="restart"
Animator sets: 動畫集合,你可以定義一組動畫,一起執行或者順序執行。<set/>,該元素的android:ordering屬性指定該組動畫是按次序播放還是同時播放。有兩個值(sequentially和together分別表示先後執行和同步執行)
Frame refresh delay:幀刷新延遲(幀刷新頻率,每個多久播放一幀);默認爲10ms,但最終依賴系統的當前狀態。
(三)、屬性動畫API:相關的類
ObjectAnimator 動畫的執行類(是ValueAnimator的子類,使用簡單常用。少數場景下,由於其存在一些限制,再考慮使用ValueAnimator)
ValueAnimator 動畫的執行類
AnimatorSet 用於控制一組動畫的執行:線性,一起,每個動畫的先後執行等。
AnimatorInflater 用戶加載屬性動畫的xml文件
TypeEvaluator 類型估值,主要用於設置動畫操作屬性的值。
TimeInterpolator 時間插值
總的來說,屬性動畫就是,動畫的執行類來設置動畫操作的對象的屬性、持續時間,開始和結束的屬性值,時間差值等,然後系統會根據設置的參數動態的變化對象的屬性。
ValueAnimator 常用方法:
1、ofFloat()小數位的動畫過渡
2、ofInt()整數位的動畫過度
3、ofObject()
4、setStartDelay()動畫播放延遲時間
5、setRepeatCount()動畫循環次數
6、setRepeatMode()循環模式:RESTART和REVERSE是重新播放和倒敘播放
valuseAnimator的使用比較簡單,可以是一個單一的過渡,沒有界面效果:
private void ValueTest(View view){
//將值從0過度到1
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
//可以設置多個這樣就是從0到1再到0.5
//ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f,0.5f);
anim.setDuration(300);
anim.start();
}
但是這樣無法知道他是否是執行了,可以通過添加一個動畫的監聽器來監聽他的回調,利用addUpdateListener()方法:anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentValue = (float) animation.getAnimatedValue();
Log.e("ceshi", "cuurent value is " + currentValue);
}
});
將結果打印出來可以看到ValueAnimator確實已經在正常工作了,值在300毫秒的時間內從0平滑過渡到了1。
也可以調用setStartDelay()設置動畫延時播放的時間,和setRepeatCount()循環次數和setRepeatMode()循環模式
不過雖說ObjectAnimator會更加常用一些,但是它其實是繼承自ValueAnimator的,底層的動畫實現機制也是基於ValueAnimator來完成的,因此ValueAnimator仍然是整個屬性動畫當中最核心的一個類。那麼既然是繼承關係,說明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它們的用法也非常類似。
如果想將圖片在3000毫秒內變成半透明再還原,可以這麼寫:
//它是可以直接對任意對象的任意屬性進行動畫操作的
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
animator.setDuration(2000);
//設置循環次數
animator.setRepeatCount(2);
//設置循環方式
animator.setRepeatMode(ValueAnimator.RESTART);
animator.start();
這裏ofFloat()內的參數中第一個需要傳入一個object對象,就是需要動畫實現的對象;第二個參數是想對對象的那個屬性進行動畫操作;
第三個和以後的參數與ValueAnimator一致;
實現效果如下:
旋轉代碼:
//設置旋轉
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0f,360f);
animator.setDuration(2000);
animator.start();
縮放代碼://設置縮放
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleX", 1.0f,0.5f,1.0f);
animator.setDuration(2000);
animator.start();
移動代碼://設置移動
//獲取圖片當前位置
float initialX = myImageView.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", initialX,-200,initialX);
animator.setDuration(5000);
//設置動畫插入器
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
效果如下:設置了動畫插入器橫向移動的時候先慢後快。
比較重要的是:
//ObjectAnimator.ofFloat第二個參數可以放置任意的值,其中(alpha、rotation、translationX、translationY和scaleY、scaleX這幾個值,分別可以完成淡入淡出、旋轉、水平或垂直移動、垂直或水平縮放縮放這幾種動畫)
實現組合動畫功能主要需要藉助AnimatorSet這個類,這個類提供了一個play()方法,如果我們向這個方法中傳入一個Animator對象(ValueAnimator或ObjectAnimator)將會返回一個AnimatorSet.Builder的實例,AnimatorSet.Builder中包括以下四個方法:
after(Animator anim) 將現有動畫插入到傳入的動畫之後執行
after(long delay) 將現有動畫延遲指定毫秒後執行
before(Animator anim) 將現有動畫插入到傳入的動畫之前執行
with(Animator anim) 將現有動畫和傳入的動畫同時執行
先整體縮放再淡入淡出,效果如下:
1、利用AnimatorSet實現組合動畫,這個是最豐富的可以實現動畫前後順序的處理
//利用AnimatorSet實現組合動畫,這個是最豐富的可以實現動畫前後順序的處理
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.5f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.5f);
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(view, "alpha", 1f, 0.5f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(scaleXAnim).with(scaleYAnim).before(alphaAnim);
animSet.setDuration(3000);
animSet.start();
2、利用動畫刷新監聽實現組合動畫,第二個參數隨便寫,只能一起執行//利用動畫刷新監聽實現組合動畫,第二個參數隨便寫,只能一起執行
ObjectAnimator anim = ObjectAnimator.ofFloat(view,"lw",1.0f,0.0f,1f);
anim.setDuration(5000);
anim.start();
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float cVal = (Float) animation.getAnimatedValue();
view.setAlpha(cVal);
view.setScaleX(cVal);
view.setScaleY(cVal);
}
});
3、除了上面Animator類還可以使用PropertyValuesHolder類來實現組合動畫,不過這個組合動畫就沒有上面的豐富了,使用PropertyValuesHolder類只能多個動畫一起執行。
當然我們得結合 ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder… values);
方法來使用。第一個參數是動畫的目標對象,之後的參數是PropertyValuesHolder類的實例,可以有多個這樣的實例。代碼如下:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ).setDuration(5000).start();
大家已經知道,ObjectAnimator是繼承自ValueAnimator的,而ValueAnimator又是繼承自Animator的,因此不管是ValueAnimator還是ObjectAnimator都是可以使用addListener()這個方法的。另外AnimatorSet也是繼承自Animator的,因此addListener()這個方法算是個通用的方法。
添加一個監聽器的代碼如下所示:
private void AnimatorListener(View view){
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0f,360f);
animator.setDuration(2000);
//第一種監聽方式
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
Log.e("ceshi", "Start");
}
@Override
public void onAnimationEnd(Animator animator) {
Log.e("ceshi", "End");
}
@Override
public void onAnimationCancel(Animator animator) {
Log.e("ceshi", "Cancel");
}
@Override
public void onAnimationRepeat(Animator animator) {
Log.e("ceshi", "Repeat");
}
});
animator.start();
animator.setRepeatCount(2);
}
第二種監聽方式,利用Android提供了一個適配器類,叫作AnimatorListenerAdapter實現動畫的監聽,代碼如下://第二種方式,可以自定義加載監聽事件,利用適配器
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
可以自定義監聽的方法,需要什麼就寫什麼。
日誌打印結果:
如果想要使用XML來編寫動畫,首先要在res目錄下面新建一個animator文件夾,所有屬性動畫的XML文件都應該存放在這個文件夾當中。然後在XML文件中我們一共可以使用如下三種標籤:
<animator> 對應代碼中的ValueAnimator
<objectAnimator> 對應代碼中的ObjectAnimator
<set> 對應代碼中的AnimatorSet
所有的都只需調用xml文件就好:
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(getApplicationContext(),R.animator.object_animator);
animator.setTarget(view);
animator.start();
ValueAnimator:valueFrom和valueTo分別是起始和終止的數值,valueType對應着ofFloat等;
<!--valueType對應着ofFloat ofInt ofObject-->
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="0"
android:valueTo="100"
android:valueType="floatType"/>
ObjectAnimator:其中propertyName是參數值可以是alpha也可以是scaleX等,跟java代碼實現差不多
<objectAnimator android:valueFrom="1"
android:valueTo="0.5"
android:valueType="floatType"
android:propertyName="alpha"
xmlns:android="http://schemas.android.com/apk/res/android" />
組合動畫:ordering 有兩個選項:sequentially 和 together 。其中 together 爲默認項。
sequentially 表示 set 中的動畫,按照先後順序逐步進行(a 完成之後進行 b )。
together 表示set 中的動畫,在同一時間同時進行。
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially" >
<!--ordering 有兩個選項:sequentially 和 together 。其中 together 爲默認項。
sequentially 表示 set 中的動畫,按照先後順序逐步進行(a 完成之後進行 b )。
together 表示set 中的動畫,在同一時間同時進行。-->
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-200"
android:valueTo="200"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="together" >
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="sequentially" >
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" >
</objectAnimator>
</set>
</set>
</set>
效果與java代碼相同。
參考了大神的博客:http://blog.csdn.net/guolin_blog/article/details/43536355
源碼:下載