Android 動畫——屬性動畫Property Animation

  Android在3.0之前只提供了兩種動畫:View Animation 、Drawable Animation 。也就是我們在《Android 動畫——Frame Animation與Tween Animation 》講解的逐幀動畫和補間動畫。Android在3.0之後又增加了一種動畫類型:Property Animation屬性動畫 。
  View Animation相當簡單,不過只能支持簡單的縮放、平移、旋轉、透明度基本的動畫,且有一定的侷限性。比如:你希望View有一個顏色的切換動畫;你希望可以使用3D旋轉動畫;你希望當動畫停止時,View的位置就是當前的位置;這些View Animation都無法做到。這就是Property Animation產生的原因,本篇博客詳細介紹Property Animation的用法。

相關API

相關屬性:

Duration:動畫的持續時間,默認300ms。
Interpolation:時間差值,定義動畫的變化率。
RepeatCount:重複次數,可以定義重複多少次。
RepeatMode:重複模式,重複播放時,是從頭開始播還是反向播。
Animator sets: 動畫集合,你可以定義一組動畫,一起執行或者順序執行。
Frame refresh delay:幀刷新延遲,動畫多久刷新一次幀;默認爲10ms。

相關類:

ValueAnimator 動畫的執行類。
ObjectAnimator 動畫的執行類,ValueAnimator的子類。
AnimatorSet 用於控制一組動畫的執行:線性,一起,每個動畫的先後執行等。
AnimatorInflater 用戶加載屬性動畫的xml文件。
TypeEvaluator 類型估值,主要用於設置動畫操作屬性的值。
TimeInterpolator 時間插值。

Animator

  Animator是動畫屬性的基類(父類),我們先看一下它的繼承結構:
  
這裏寫圖片描述

Animator有兩個子類:
ValueAnimator :是屬性動畫的時間引擎,主要用於爲屬性動畫計算相關屬性的值。它也包含兩個子類:ObjectAnimator,TimeAnimator
AnimatorSet:用於組合多個Animator。

ValueAnimator的使用

  ValueAnimator使用代碼創建和它的子類ObjectAnimator使用代碼創建是有區別的。這裏先聲明一下,在下面講解到ObjectAnimator我們會具體的說明。ValueAnimator使用代碼創建步驟如下:
  
1. 首先調用ValueAnimator如下的靜態方法設置相關的屬性值:

這裏寫圖片描述

  這裏我們調用ofFloat(float… values)屬性傳入動畫在X軸上變化的數值。
  
2. ValueAnimator對象調用setTarget()方法,設置動畫實現在哪個對象的身上。
3. ValueAnimator對象調用setDuration()和start()設置動畫的顯示時間和開始動畫。
4. 調用addUpdateListener()方法,在這個監聽器中添加相關的操作。
我們來看具體的代碼操作:
xml佈局文件:(一個按鈕開始動畫,一個ImageView顯示動畫)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center">

        <Button
            android:id="@+id/button_start"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="開始動畫" />

    </LinearLayout>
    <ImageView
        android:id="@+id/imageview_xml"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:onClick="startAnimation"
        android:src="@mipmap/ic_launcher" />

</RelativeLayout>

Activity代碼實現:

public class XMLAnimationActivity extends Activity implements View.OnClickListener {

    private Button mButtonStart;
    private ImageView mImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_xmlanimation);
        mButtonStart = (Button) findViewById(R.id.button_start);
        mImageView = (ImageView) findViewById(R.id.imageview_xml);
        mButtonStart.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_start:
                //在代碼中創建
                ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f);//設置屬性值
                animator.setTarget(mImageView);//設置操作對象
                animator.setDuration(1000).start();//動畫開始
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        mImageView.setScaleY((Float) animation.getAnimatedValue());//設置Y軸上的變化
                        mImageView.setScaleX((Float) animation.getAnimatedValue());//設置X軸上的變化
                    }
                });
                break;
            default:
                break;
        }
    }
}

這裏寫圖片描述

ObjectAnimator的使用

  ObjectAnimator創建有兩種方式,一種是在java代碼中添加,一種是使用加載xml佈局添加。

java代碼中創建

在Activity中添加一句話:

ObjectAnimator.ofFloat(mImageView, "ScaleX", 0.0f, 1.0f).setDuration(3000).start();

  ObjectAnimator提供了ofInt、ofFloat、ofObject,這幾個方法都是設置動畫作用的元素、作用的屬性、動畫開始、結束、以及中間的任意個屬性值。當對於屬性值,只設置一個的時候,會認爲當然對象該屬性的值爲開始(getPropName反射獲取),然後設置的值爲終點。如果設置兩個,則一個爲開始、一個爲結束。
  動畫更新的過程中,會不斷調用setPropName更新元素的屬性,所有使用ObjectAnimator更新某個屬性,必須得有getter(設置一個屬性值的時候)和setter方法。
  
這裏寫圖片描述

xml文件中創建

  爲了減輕java代碼的負擔,我們將對動畫的設置定義在xml代碼中。
1. 首先在res文件夾下創建一個animator的文件夾。
2. 在animator文件夾下創建一個animator.xml的文件。我們在該xml文件下對動畫屬性定義。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="3000"
        android:propertyName="scaleX"
        android:valueFrom="0.5f"
        android:valueTo="1.0f">
    </objectAnimator>
</set>

3. 在Activity中:

//使用xml文件加載屬性動畫方式一
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator);//通過該方法,將xml文件導入
anim.setTarget(mImageView);//這是動畫的對象
anim.start();//設置動畫的開始

這裏寫圖片描述

以下爲補充:
  其實在之前還有一種調用方式:在ImageView中添加android:onClick="startAnimation"屬性,然後再Activity中定義如下方法:
  注意:該方法已被拋棄,因爲他增加了xml佈局文件與java文件的耦合性,違背了”高內聚,低耦合“的原則。

    public void startAnimation(View view) {
        //java代碼中設置屬性操作
        ObjectAnimator.ofFloat(mImageView, "TranslationZ", 0.0f, 1.0f).setDuration(3000).start();    
    }
    public void startAnimation(View view) {
        //xml文件中設置屬性操作
        Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator);
        anim.setTarget(mImageView);
        anim.start();      
    }

這裏寫圖片描述

ObjectAnimator與ValueAnimator的不同

我們可以先回顧一下ValueAnimator的使用:

ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f);//設置屬性值
animator.setTarget(mImageView);//設置操作對象
animator.setDuration(1000).start();//動畫開始
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        mImageView.setScaleY((Float) animation.getAnimatedValue());//設置Y軸上的變化
        mImageView.setScaleX((Float) animation.getAnimatedValue());//設置X軸上的變化
    }
});

ObjectAnimator使用:

ObjectAnimator.ofFloat(mImageView, "ScaleX", 0.0f, 1.0f).setDuration(3000).start();

  區別很明顯,ValueAnimator調用ofFloat()方法設置了操作的值,而沒有設置是何種操作,也就是沒有設置操作屬性。而ObjectAnimator調用ofFloat()方法設置了操作屬性是ScaleX(X軸變化)。
  
  ValueAnimator有沒有設置操作的屬性,也就是說我們必須在addUpdateListener()方法中定義的監聽器中添加相關的屬性,否則動畫沒有任何的操作。那麼ValueAnimator這樣有什麼好處呢?
  
  好處就是,我們不需要操作的對象的屬性一定要有getter和setter方法,你可以自己根據當前動畫的計算值,來操作任何屬性。
  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章