前言:
前面兩篇介紹了Android的Tween Animation(補間動畫) Android動畫效果之Tween Animation(補間動畫)、Frame Animation(逐幀動畫)Android動畫效果之Frame Animation(逐幀動畫)(二),其實總結前兩個的根本目的就是為了學習今天的主角Property Animation(屬性動畫)。其實在Android最早期只提供了前兩種動畫方式,在Android 3.0才引入了屬性動畫,谷歌為何要引入屬性動畫呢?今天我們來總結學習一下。
其他幾種動畫效果:
- Android動畫效果之Tween Animation(補間動畫)
- Android動畫效果之Frame Animation(逐幀動畫)
- Android動畫效果之初識Property Animation(屬性動畫)
- Android動畫效果之Property Animation進階(屬性動畫)
- Android動畫效果之自定義ViewGroup新增布局動畫
Property Animation產生的背景:
由於Tween Animation(補間動畫)只能實現簡單的四種的動畫(alpha、scale、rotate、translate),要想實現比較複雜的動畫就難以滿足需求,而且補間動畫只是改變了View物件繪製的位置,而沒有改變View物件本身,比如View形狀的變換,如大小的縮放,透明度的改變,位置的改變,其實本身並沒有改變,舉個例子就好比孫悟空靈魂出竅一樣,雖然已經上天入地,其實肉體還在那裡一動不動,我們開發過程中的經常遇見的就是translate之後事件還在原地。如果要實現既要有動畫效果又要使得View本身得到真正改變,那就要藉助屬性動畫了,這也是屬性動畫引入的原因。它能夠更加靈活的實現各種效果,不僅限於類似補間動畫實現的哪幾種效果。
Property Animation相關類
屬性動畫,根據字面理解可以通過修改物件的屬性值以達到動畫效果。
類名 | 用途 |
ValueAnimator | 屬性動畫主要的計時器,也計算動畫後的屬性的值,動畫的執行類 |
ObjectAnimator | ValueAnimator的一個子類,允許你設定一個目標物件和物件的屬性進行動畫,動畫的執行類 |
AnimatorSet | 提供組織動畫的結構,使它們能相關聯得執行,用於控制一組動畫的執行 |
AnimatorInflater | 使用者載入屬性動畫的xml檔案 |
Evaluators | 屬性動畫計算器,告訴了屬性動畫系統如何計算給出屬性的值 |
Interpolators | 動畫插入器,定義動畫的變化率 |
上面幾個重要類之間的關係如下圖所示:
今天先通過最簡單最容易理解的ObjectAnimator來學習總結。
ObjectAnimator:
ValueAnimator的一個子類,允許你設定一個目標物件和物件的屬性進行動畫。當這個類計算好一個動畫的新值後,相應的會更新其屬性。大多數時候你都會想用ObjectAnimator,因為它使得動畫值到目標物件的處理更簡單了。
1.)以實現一個View透明漸變效果為例進行說明
xml實現方式:
這裡需要注意是的屬性動畫檔案存放目錄為res/animator
<?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" />
duration 表示動畫執行的時間
propertyName 表示修改的物件的哪個屬性值,這裡是透明度
valueFrom 表示從哪個狀態值開始動畫
valueTo 表示到哪個狀態值結束動畫
valueType 型別估值,主要用於設定動畫操作屬性的值
repeatMode 表示重複的模式 reverse表示
repeatCount 動畫重複的計數,動畫將會執行該值+1次
repeatMode 動畫重複的模式,reverse為反向,當第偶次執行時,動畫方向會相反。restart為重新執行,方向不變
startOffset, 動畫多次執行的間隔時間,如果只執行一次,執行前會暫停這段時間,單位毫秒
interpolator 指定動畫插入器
通過上面的xml屬性可以看出和補間動畫基本上一致,然後通過AnimatorInflater 來載入xml中的動畫
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_alpha); anim.setTarget(imageView); anim.start();
當然也可以通過純Java程式碼的方式實現
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();
對於java程式碼實現,ObjectAnimator 提供了以下幾個方法:ofFloat(),ofInt(),ofObject(),ofArgb(),ofPropertyValuesHolder()這幾個方法都是設定動畫作用的元素、作用的屬性、動畫開始、結束、以及中間的任意個屬性值。
其他舉例:
縮放動畫:
xml:
<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" />
java程式碼:
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.5f); scaleXAnimator.setDuration(500); scaleXAnimator.setRepeatCount(1); scaleXAnimator.setRepeatMode(ValueAnimator.REVERSE); scaleXAnimator.start();
旋轉動畫:
xml:
<?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" />
java程式碼:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f); objectAnimator.setDuration(500); objectAnimator.setRepeatCount(1); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); objectAnimator.start();
平移動畫:
xml:
<?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" />
java程式碼:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0f, 100f); objectAnimator.setDuration(500); objectAnimator.setRepeatCount(1); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); objectAnimator.start();
2.)如何實現一個組合動畫
舉例我們同時對一個控制元件進行寬高兩個維度的縮放
方式一:使用AnimatorSet
<?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>
載入xml動畫
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_scale); anim.setTarget(imageView); anim.start();
純Java程式碼實現:
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();
上述程式碼通過
playTogether函式實現兩個動畫同時執行,如果不想同時執行,也可以呼叫play函式返回AnimatorSet.Builder例項,AnimatorSet.Builder提供瞭如下幾個函式用於實現動畫組合:
- after(Animator anim) 將現有動畫插入到傳入的動畫之後執行
- after(long delay) 將現有動畫延遲指定毫秒後執行
- before(Animator anim) 將現有動畫插入到傳入的動畫之前執行
- with(Animator anim) 將現有動畫和傳入的動畫同時執行
也可以呼叫playSequentially函式實現分佈執行動畫。
方式二:使用PropertyValuesHolder
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();
通過這種方式只能實現同時執行的動畫組合相比AnimatorSet就沒那麼豐富了,PropertyValuesHolder 提供的函式方法有如下幾種: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,能夠實現的動畫相對單一,只能實現比如縮放,透明度改變,平移、旋轉等,具體函式名字:平移 translationX,translationY, X,Y,縮放 scaleX,scaleY, 旋轉 rotationX, rotationY,
透明度 alpha
3.)設定動畫監聽器
有時候我們可能要在某一個動畫執行之前 或者動畫結束之後進行一些其他的操作,這個時候就要藉助動畫監聽器了。
objectAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { //TODO 動畫開始前的操作 } @Override public void onAnimationEnd(Animator animation) { //TODO 動畫結束的操作 } @Override public void onAnimationCancel(Animator animation) { //TODO 動畫取消的操作 } @Override public void onAnimationRepeat(Animator animation) { //TODO 動畫重複的操作 } });
如果我們需要簡單動畫執行過程中的變化可以使用AnimatorUpdateListener
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); //可以根據自己的需要來獲取動畫更新值。 Log.e("AnimatorUpdateListener", "the animation value is " + value); } });
總結:
本篇主要先簡單認識一下屬性動畫,以及利用屬性動畫實現補間動畫。後續會對屬性動畫進行進一步的學習。