Android動畫效果之初識Property Animation(屬性動畫)

http://www.cnblogs.com/whoislcj/p/5796803.html

Android動畫效果之初識Property Animation(屬性動畫)

前言:

 前面兩篇介紹了Android的Tween Animation(補(bǔ)間動畫) Android動畫效果之Tween Animation(補(bǔ)間動畫)、Frame Animation(逐幀動畫)Android動畫效果之Frame Animation(逐幀動畫)(二),其實(shí)總結(jié)前兩個的根本目的就是為了學(xué)習(xí)今天的主角Property Animation(屬性動畫)。其實(shí)在Android最早期只提供了前兩種動畫方式,在Android 3.0才引入了屬性動畫,谷歌為何要引入屬性動畫呢?今天我們來總結(jié)學(xué)習(xí)一下。

Property Animation產(chǎn)生的背景:
由于Tween Animation(補(bǔ)間動畫)只能實(shí)現(xiàn)簡單的四種的動畫(alpha、scale、rotate、translate),要想實(shí)現(xiàn)比較復(fù)雜的動畫就難以滿足需求,而且補(bǔ)間動畫只是改變了View對象繪制的位置,而沒有改變View對象本身,比如View形狀的變換,如大小的縮放,透明度的改變,位置的改變,其實(shí)本身并沒有改變,舉個例子就好比孫悟空靈魂出竅一樣,雖然已經(jīng)上天入地,其實(shí)肉體還在那里一動不動,我們開發(fā)過程中的經(jīng)常遇見的就是translate之后事件還在原地。如果要實(shí)現(xiàn)既要有動畫效果又要使得View本身得到真正改變,那就要借助屬性動畫了,這也是屬性動畫引入的原因。它能夠更加靈活的實(shí)現(xiàn)各種效果,不僅限于類似補(bǔ)間動畫實(shí)現(xiàn)的哪幾種效果。

Property Animation相關(guān)類
屬性動畫,根據(jù)字面理解可以通過修改物件的屬性值以達(dá)到動畫效果。

類名 用途
ValueAnimator 屬性動畫主要的計(jì)時器,也計(jì)算動畫后的屬性的值,動畫的執(zhí)行類
ObjectAnimator ValueAnimator的一個子類,允許你設(shè)置一個目標(biāo)對象和對象的屬性進(jìn)行動畫,動畫的執(zhí)行類
AnimatorSet 提供組織動畫的結(jié)構(gòu),使它們能相關(guān)聯(lián)得運(yùn)行,用于控制一組動畫的執(zhí)行
AnimatorInflater 用戶加載屬性動畫的xml文件
Evaluators 屬性動畫計(jì)算器,告訴了屬性動畫系統(tǒng)如何計(jì)算給出屬性的值
Interpolators 動畫插入器,定義動畫的變化率

今天先通過最簡單最容易理解的ObjectAnimator來學(xué)習(xí)總結(jié)。

ObjectAnimator:
ValueAnimator的一個子類,允許你設(shè)置一個目標(biāo)對象和對象的屬性進(jìn)行動畫。當(dāng)這個類計(jì)算好一個動畫的新值后,相應(yīng)的會更新其屬性。大多數(shù)時候你都會想用ObjectAnimator,因?yàn)樗沟脛赢嬛档侥繕?biāo)對象的處理更簡單了。

1.)以實(shí)現(xiàn)一個View透明漸變效果為例進(jìn)行說明
xml實(shí)現(xiàn)方式:

這里需要注意是的屬性動畫文件存放目錄為res/animator

復(fù)制代碼
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:propertyName="alpha"
android:repeatCount="1"
android:repeatMode="reverse"
android:startOffset="200"
android:valueFrom="0.0"
android:valueTo="1.0"
android:valueType="floatType" />
復(fù)制代碼
duration 表示動畫執(zhí)行的時間

propertyName 表示修改的物件的哪個屬性值,這里是透明度

valueFrom 表示從哪個狀態(tài)值開始動畫

valueTo 表示到哪個狀態(tài)值結(jié)束動畫

valueType 類型估值,主要用于設(shè)置動畫操作屬性的值

repeatMode 表示重復(fù)的模式 reverse表示

repeatCount 動畫重復(fù)的計(jì)數(shù),動畫將會執(zhí)行該值+1次

repeatMode 動畫重復(fù)的模式,reverse為反向,當(dāng)?shù)谂即螆?zhí)行時,動畫方向會相反。restart為重新執(zhí)行,方向不變

startOffset, 動畫多次執(zhí)行的間隔時間,如果只執(zhí)行一次,執(zhí)行前會暫停這段時間,單位毫秒

interpolator 指定動畫插入器

通過上面的xml屬性可以看出和補(bǔ)間動畫基本上一致,然后通過AnimatorInflater 來加載xml中的動畫

Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_alpha);
anim.setTarget(imageView);
anim.start();
當(dāng)然也可以通過純Java代碼的方式實(shí)現(xiàn)

復(fù)制代碼
ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
alphaAnimation.setDuration(500);
alphaAnimation.setRepeatCount(0);
alphaAnimation.setRepeatMode(ValueAnimator.REVERSE);
alphaAnimation.setStartDelay(200);
alphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
alphaAnimation.start();
復(fù)制代碼
對于java代碼實(shí)現(xiàn),ObjectAnimator 提供了以下幾個方法:ofFloat(),ofInt(),ofObject(),ofArgb(),ofPropertyValuesHolder()這幾個方法都是設(shè)置動畫作用的元素、作用的屬性、動畫開始、結(jié)束、以及中間的任意個屬性值。

其他舉例:

縮放動畫:
xml:

復(fù)制代碼
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
  android:duration="500"
  android:propertyName="scaleX"
  android:repeatCount="1"
  android:repeatMode="reverse"
  android:valueFrom="1.0"
  android:valueTo="1.5"
  android:valueType="floatType" />
復(fù)制代碼
java代碼:

ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.5f);
scaleXAnimator.setDuration(500);
scaleXAnimator.setRepeatCount(1);
scaleXAnimator.setRepeatMode(ValueAnimator.REVERSE);
scaleXAnimator.start();
旋轉(zhuǎn)動畫:
xml:

復(fù)制代碼
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="rotation"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" />
復(fù)制代碼
java代碼:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);
objectAnimator.setDuration(500);
objectAnimator.setRepeatCount(1);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.start();
平移動畫:
xml:

復(fù)制代碼
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:propertyName="translationX"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="100"
android:valueType="floatType" />
復(fù)制代碼
java代碼:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0f, 100f);
objectAnimator.setDuration(500);
objectAnimator.setRepeatCount(1);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.start();
2.)如何實(shí)現(xiàn)一個組合動畫
舉例我們同時對一個控件進(jìn)行寬高兩個維度的縮放

方式一:使用AnimatorSet
復(fù)制代碼
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<objectAnimator
android:duration="500"
android:propertyName="scaleX"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="1.0"
android:valueTo="1.5"
android:valueType="floatType" />
<objectAnimator
android:duration="500"
android:propertyName="scaleY"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="1.0"
android:valueTo="1.5"
android:valueType="floatType" />

</set>
復(fù)制代碼
加載xml動畫

Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_scale);
  anim.setTarget(imageView);
  anim.start();

純Java代碼實(shí)現(xiàn):

復(fù)制代碼
AnimatorSet animatorSet = new AnimatorSet();

ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.5f);
scaleXAnimator.setDuration(500);
scaleXAnimator.setRepeatCount(1);
scaleXAnimator.setRepeatMode(ValueAnimator.REVERSE);
scaleXAnimator.start();

ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 1.5f);
scaleYAnimator.setDuration(500);
scaleYAnimator.setRepeatCount(1);
scaleYAnimator.setRepeatMode(ValueAnimator.REVERSE);

animatorSet.playTogether(scaleXAnimator, scaleYAnimator);
animatorSet.start();

復(fù)制代碼
上述代碼通過playTogether函數(shù)實(shí)現(xiàn)兩個動畫同時執(zhí)行,如果不想同時執(zhí)行,也可以調(diào)用play函數(shù)返回AnimatorSet.Builder實(shí)例,AnimatorSet.Builder提供了如下幾個函數(shù)用于實(shí)現(xiàn)動畫組合:

after(Animator anim) 將現(xiàn)有動畫插入到傳入的動畫之后執(zhí)行
after(long delay) 將現(xiàn)有動畫延遲指定毫秒后執(zhí)行
before(Animator anim) 將現(xiàn)有動畫插入到傳入的動畫之前執(zhí)行
with(Animator anim) 將現(xiàn)有動畫和傳入的動畫同時執(zhí)行
也可以調(diào)用playSequentially函數(shù)實(shí)現(xiàn)分布執(zhí)行動畫。

方式二:使用PropertyValuesHolder
復(fù)制代碼
PropertyValuesHolder scaleXValuesHolder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f);
PropertyValuesHolder scaleYValuesHolder = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 1.5f);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, scaleXValuesHolder, scaleYValuesHolder);
objectAnimator.setDuration(500);
objectAnimator.setRepeatCount(1);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.start();
復(fù)制代碼
通過這種方式只能實(shí)現(xiàn)同時執(zhí)行的動畫組合相比AnimatorSet就沒那么豐富了,PropertyValuesHolder 提供的函數(shù)方法有如下幾種:ofInt()、ofFloat()、ofObject()、ofKeyframe()。

方式三:使用ViewPropertyAnimator
ViewPropertyAnimator viewPropertyAnimator=imageView.animate();
viewPropertyAnimator.scaleXBy(1.0f).scaleX(1.5f).scaleYBy(1.0f).scaleY(1.5f).setDuration(500).start();
多屬性動畫,作用于View,能夠?qū)崿F(xiàn)的動畫相對單一,只能實(shí)現(xiàn)比如縮放,透明度改變,平移、旋轉(zhuǎn)等,具體函數(shù)名字:平移 translationX,translationY, X,Y,縮放 scaleX,scaleY, 旋轉(zhuǎn) rotationX, rotationY,透明度 alpha

3.)設(shè)置動畫監(jiān)聽器
有時候我們可能要在某一個動畫執(zhí)行之前 或者動畫結(jié)束之后進(jìn)行一些其他的操作,這個時候就要借助動畫監(jiān)聽器了。

復(fù)制代碼
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
//TODO 動畫開始前的操作
}

@Override
public void onAnimationEnd(Animator animation) {
    //TODO 動畫結(jié)束的操作
}

@Override
public void onAnimationCancel(Animator animation) {
   //TODO 動畫取消的操作
}

@Override
public void onAnimationRepeat(Animator animation) {
    //TODO 動畫重復(fù)的操作
}
});

復(fù)制代碼
如果我們需要簡單動畫執(zhí)行過程中的變化可以使用AnimatorUpdateListener

復(fù)制代碼
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
//可以根據(jù)自己的需要來獲取動畫更新值。
Log.e("AnimatorUpdateListener", "the animation value is " + value);
}
});
復(fù)制代碼

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容