Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 動畫系列之屬性(Property)動畫詳解

Android 動畫系列之屬性(Property)動畫詳解

編輯:關於Android編程

前言

今天有時間來繼續寫寫屬性動畫。

簡介

眾所周知,屬性動畫是Android3.0版本開始的,一個東西的推出肯定是有它的道理的,那為什麼前面已經有逐幀和補間動畫了還要推出屬性動畫呢?

在前2篇的補間動畫中我們知道了我們可以對一個View進行:縮放、旋轉、平移、淡入淡出操作,並且可以做自定義補間動畫的操作。但是自定義補間動畫操作起來很麻煩,而自帶的那幾種使用起來雖然簡單,但是也僅限於這幾種了,補間動畫的機制其實就是使用硬編碼來完成的,功能已經限定死了,基本沒有任何擴展性可言。還有就是如果我們使用補間動畫使View往右移動一段距離,那麼其實這個View依然還在原點,並沒有真正移動,而使用屬性動畫移動到那個點就是在那個點。還有一個重要的點是,補間動畫只能夠作用在View上的,那麼如果你想對其他非View對象進行動畫操作,那就GG了。說了這麼多,相信大家已經知道補間和屬性動畫的區別了。

屬性動畫其對應的類是Animator,和補間動畫中的Animation一樣,Animator也是一個抽象類,其對應的繼承關系如下圖:
這裡寫圖片描述

Animator

Animator有如下方法:
* addListener(Animator.AnimatorListener listener):監聽動畫的開始、重復、和結束。
* addPauseListener(Animator.AnimatorPauseListener listener):為動畫添加一個暫停監聽。
* cancel() :取消動畫
* clone():對動畫進行拷貝。
* end():結束動畫。
* getDuration():獲取動畫的持續時間。
* getInterpolator():獲取動畫的時間插補器。
* getListeners():獲取監聽器集合。
* getStartDelay():獲取動畫延遲開始的時間。
* isPaused():檢查動畫是否處於暫停狀態。
* isRunning():檢查動畫是否正在運行(已經啟動,並走過了startDelay(),尚未結束)
* isStarted():檢查動畫是否已經開始,沒有結束。
* pause():暫停正在運動的動畫。
* removeAllListeners():刪除所有的listeners 與pauseListeners對象。
* removeListener(Animator.AnimatorListener listener):移除指定的AnimatorListener監聽器。
* removePauseListener(Animator.AnimatorPauseListener listener):移除指定的AnimatorPauseListene監聽器。
* resume():恢復已經暫停的動畫。
* setDuration(long duration):設置動畫持續時間。
* setInterpolator(TimeInterpolator value):設置時間插值器。
* setStartDelay(long startDelay):設置動畫延遲多少毫秒後start()方法被調用。
* setTarget(Object target):設置目標對象。
* start():啟動動畫。

由於Animator是屬性動畫的基類,那麼其子類也都有上面的方法。我們在具體使用中我們通常會使用它的子類,下面具體來看看子類的使用。

ObjectAnimator

首先來用ObjectAnimator實現下補間動畫中的操作。因為ObjectAnimator繼承自ValueAnimator,使用起來是最簡單的,分分鐘實現一個動畫:
* 新建一個布局文件:




    
代碼中實現點擊事件開啟了一個旋轉動畫:
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void startAnim(View v){
        ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(v, "rotation", 0.0f, 360f);
        rotateAnim.setDuration(3000);
        rotateAnim.start();

    }
}

運行結果:
這裡寫圖片描述
可以看到,我們調用ofFloat(Object target, String propertyName, float… values) 構建ObjectAnimatZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcsqxuvKjrNa7tKvI68HL1eK49ravu63SqrLZ1/e1xFZpZXejrNLUvLCy2df31eK49lZpZXe1xMr00NSjrLu509C+zcrHv8mx5LLOo6y+zcq1z9bBy9K7uPa2r7utoaM8L3A+DQo8cD7Ex8O0zsrM4sC0wcujrLP9wcu0q8jrcm90YXRpb27K9NDU1q7N4qOsu7m/ydLUtKvI68m2yvTQ1MTYo788YnIgLz4NCsbkyrXU2s7Sw8fKudPDT2JqZWN0QW5pbWF0b3LX9ravu621xMqxuvKjrLKisrvKx7j5vt1YTUzW0Lao0uW1xMr00NTAtLjEseS1xKOstvjKx8ilzai5/da4tqi1xMr00NTIpbLp1dLL+bbU09q1xGdldKGic2V0t723qMC0uMSx5LXEoaPEx87Sw8fJz8PmtcSy2df3tcRJbWFnZVZpZXfT0HNldFJvdGF0aW9uKCm3vbeow7Sjv7TwsLjKx9PQtcSho7a8ysfNqLn9Vmlld7zMs9C2+MC0tcSho87Sw8e/ydLUv7S/tFZpZXfW0NK7ubLT0MTE0KnP4LnYtcS3vbeoo7o8L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;"> //1、透明度:alpha public void setAlpha(float alpha) //2、旋轉度數:rotation、rotationX、rotationY public void setRotation(float rotation) public void setRotationX(float rotationX) public void setRotationY(float rotationY) //3、平移:translationX、translationY public void setTranslationX(float translationX) public void setTranslationY(float translationY) //縮放:scaleX、scaleY public void setScaleX(float scaleX) public void setScaleY(float scaleY)

知道了有哪些之後,我們可以繼續來驗證一下其他的動畫。

平移動畫:
ObjectAnimator moveAnim = ObjectAnimator.ofFloat(v, "translationX", v.getTranslationX(), -200.0f, v.getTranslationX());
moveAnim.setDuration(3000);
moveAnim.start();

運行結果:
這裡寫圖片描述
* 透明動畫:

ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(v, "alpha", 0.0f, 1.0f);
alphaAnim.setDuration(3000);
alphaAnim.start();

運行結果:
這裡寫圖片描述
* 縮放動畫:

ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(v, "scaleX", 1.0f, 0.0f, 2.0f, 1.0f);
scaleAnim .setDuration(3000);
scaleAnim .start();

運行結果:
這裡寫圖片描述
關於ObjectAnimator,我們只需知道一些簡單的用法就行了,真正的重頭戲在後面。

ValueAnimator

ValueAnimator直接繼承自抽象類Animator,它是整個屬性動畫中最核心的一個類了,其實上面寫到的ObjectAnimator就是對ValueAnimator的一個封裝實現。可以讓我們更方便的實現簡單的動畫效果。

屬性動畫的運行機制是通過不斷的對值進行操作來實現的,我們只需要把初始值和結束值給ValueAnimator,其內部會使用一種時間循環的機制來計算值與值之間的動畫過渡,來自動幫我們完成從初始值到結束值的平滑過度效果。

首先來看看ValueAnimator的用法,其實和ObjectAnimator類似,只不過少了屬性值的參數:

ValueAnimator animator = ValueAnimator.ofFloat(0f, 100f);
animator.setDuration(300);
animator.start();

可以看到,其實同構ObjectAnimator對比,ValueAnimator通過of…構建對象的參數只有一個可變參,而沒有了作用的View和屬性名。
這是因為,ValueAnimator只提供了平滑過度的值,而你要用這個值做什麼,完全由自己決定。

我們可以通過監聽來打印看看ValueAnimator提供給我們的值:

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float value  = (float) animation.getAnimatedValue();
        Log.i("test", "value: " + value);
    }
});

打印結果:

07-30 10:05:56.128 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 0.0
07-30 10:05:56.145 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 0.7902175
07-30 10:05:56.163 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 3.1359017
07-30 10:05:56.179 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 7.231784
07-30 10:05:56.200 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 12.494448
07-30 10:05:56.220 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 18.942606
07-30 10:05:56.232 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 26.372465
07-30 10:05:56.249 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 35.047955
07-30 10:05:56.266 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 43.733345
07-30 10:05:56.283 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 52.616795
07-30 10:05:56.300 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 61.417534
07-30 10:05:56.318 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 70.33683
07-30 10:05:56.335 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 78.10417
07-30 10:05:56.352 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 84.98317
07-30 10:05:56.369 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 90.756386
07-30 10:05:56.387 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 95.46181
07-30 10:05:56.404 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 98.42916
07-30 10:05:56.421 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 99.86572
07-30 10:05:56.438 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 100.0

通過ValueAnimator實現位移動畫:

ValueAnimator animator = ValueAnimator.ofFloat(0f, 100f, -100f, 0f);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float value  = (float) animation.getAnimatedValue();
        v.setTranslationY(value);
    }
});
animator.start();

運行結果:
這裡寫圖片描述

AnimatorSet

AnimatorSet用於實現組合動畫,這個類提供了一個play()方法,如果我們向這個方法中傳入一個Animator對象(ValueAnimator或ObjectAnimator)將會返回一個AnimatorSet.Builder的實例,AnimatorSet.Builder中包括以下四個方法:

after(Animator anim) 將傳入的動畫在原有動畫執行之前執行:
// 將after中傳入的縮放動畫在原有動畫之前執行
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(v, "rotation", 0.0f, 360f);
ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(v, "scaleX", 1.0f, 0.0f, 2.0f, 1.0f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(rotateAnim).after(scaleAnim);
animSet.setDuration(1000);
animSet.start();

運行結果:
這裡寫圖片描述

after(long delay) 將現有動畫延遲指定毫秒後執行:
animSet.play(rotateAnim).after(1000);

運行結果:
這裡寫圖片描述
* before(Animator anim) 將插入的動畫在原有動畫執行之後執行:

animSet.play(rotateAnim).before(scaleAnim);

運行結果:
這裡寫圖片描述
* with(Animator anim) 將插入的動畫和原有動畫同時執行:

animSet.play(rotateAnim).with(scaleAnim);

運行結果:
這裡寫圖片描述

PropertyValuesHolder

除了上面使用AnimatorSet實現了一組動畫播放之外,我們還可以通過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(v, pvhX, pvhY,pvhZ).setDuration(1000).start();

運行結果:
這裡寫圖片描述

動畫監聽

Animator提供了一個動畫監聽的方法:addListener(),通過傳入一個AnimatorListener來實現監聽:

rotateAnim.addListener(new Animator.AnimatorListener() {

    // 動畫開始的時候調用
    @Override
    public void onAnimationStart(Animator animation) {

    }

    // 動畫結束的時候調用
    @Override
    public void onAnimationEnd(Animator animation) {

    }

    // 動畫被取消的時候調用
    @Override
    public void onAnimationCancel(Animator animation) {

    }

    // 動畫重復執行的時候調用
    @Override
    public void onAnimationRepeat(Animator animation) {

    }
});

如果你只想監聽動畫的結束,而又覺得每次都得實現所有的接口很繁瑣,那麼你可以試試Andorid給我們提供的適配器類:AnimatorListenerAdapter

rotateAnim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
    }
});

需要監聽哪個事件,只需單獨重寫一下該方法就行了。

XML定義屬性動畫

除了在代碼中使用外,我們還可以在XML文件中定義屬性動畫。其中定義屬性動畫的XML資源文件能以如下三個元素中任意一個作為根元素:
* :該元素定義的資源代表AnimatorSet對象,它是一個父元素,用於包含

XML中定義ObjectAnimator


代碼中使用:

Animator animator = AnimatorInflater.loadAnimator(this, R.animator.anim_property);
animator.setTarget(v);
animator.start();

運行結果:
這裡寫圖片描述

XML中定義ValueAnimator


代碼中使用:

ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.anim_property);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        int value = (int) animation.getAnimatedValue();
        Log.i("test", "value: " + value);
    }
});
animator.start();

運行結果:
這裡寫圖片描述

XML中定義AnimatorSet




    

代碼:

Animator animator = AnimatorInflater.loadAnimator(this, R.animator.anim_property);
animator.setDuration(300);
animator.setTarget(v);
animator.start();

運行結果:
這裡寫圖片描述

總結

合適的運用動畫會使我們的應用更有逼格。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved