使用兩種方式完成四種彈性動畫
前言
最近這段時間對彈性動畫比較感興趣,空閒就做了一下彈性動畫的實現。網上對彈性動畫的實現其實是有3種,屬性動畫設定spring插值器、facebook出的rebound以及google出的SpringAnimation。考慮到android的google背景以及想重溫一下屬性動畫的使用,本博實現了第一種和第三種。
最終實現效果
注意上述動態圖介面的title,第一個介面是屬性動畫差值器的實現,第二個介面是SpringAnimation的實現。每一種實現都做了四種常見的動畫操作:縮放、平移、旋轉、淡入淡出。
思路及程式碼
所謂“彈性動畫”,其實就是控制元件的某個屬性值在到達某個值之後在該值的左右來回變化(變得比改之大,或變得比該值小),最終穩定在該值的效果。這種變化的動畫很像彈簧,所以就叫做“彈性動畫”。這種變化作用在view的縮放參數(scaleX、scaleY)、平移引數(transactionX、transactionY)、旋轉引數(rotation)、透明度引數(alpha)上會有物理運動的那種平滑過渡的效果,比直接到達該值的那種生硬好很多很多,這也是“彈性動畫”的意義了。
插值器實現
屬性動畫的彈性效果實現,是利用插值器。而選擇合適的插值器函式至關重要,網上的一篇文章直接給出了函式:pow(2, -10 * x) * sin((x - factor / 4) * (2 * PI) / factor) + 1,我們就可以利用這個函式建立自己的插值器實現此效果:
public class SpringInterpolator implements Interpolator {
private float factor;
public SpringInterpolator(float factor) {
this.factor = factor;
}
@Override
public float getInterpolation(float input) {
//factor = 0.4
// pow(2, -10 * x) * sin((x - factor / 4) * (2 * PI) / factor) + 1
return (float) (Math.pow(2, -10 * input) * Math.sin((input - factor / 4) * (2 * Math.PI) / factor) + 1);
}
}
需要注意的是,此插值器除了在0~1之間線性變化的input這個輸入引數外,還有一個factor的輸入引數。那此引數是做什麼的呢?我們可以做一個實驗,做實驗的地方是在
我們修改factor的值為0.1,曲線圖變成了這樣:
再次修改factor的值為0.9,曲線圖是這樣:
由上述三圖就可以得出結論:factor的值越小,值來回變化的次數越多,對應到具體的動畫就是:factor值越小,view來回縮放的次數越多,平移到指定位置後在指定位置上下或左右擺動的次數也越多,旋轉和淡入淡出類似。
下面看一下屬性動畫的實現部分,因為屬性動畫的使用都是差不多,這裡只列出其中的一次使用:
//建立兩個物件動畫的例項和將這個例項組合起來的組合物件例項
ObjectAnimator objectAnimator0 = null;
ObjectAnimator objectAnimator1 = null;
AnimatorSet animatorSet = new AnimatorSet();
//指定修改view的哪個屬性及屬性的起始值和結束值
objectAnimator0 = ObjectAnimator.ofFloat(imageview, "scaleX", 1.0f, 2.0f);
objectAnimator1 = ObjectAnimator.ofFloat(imageview, "scaleY", 1.0f, 2.0f);
//指定兩個物件動畫的執行順序
animatorSet.playTogether(objectAnimator0, objectAnimator1);
//指定兩個動畫組合之後的執行時間
animatorSet.setDuration(2500);
//指定插值器
animatorSet.setInterpolator(new SpringInterpolator(0.3f));
//啟動動畫
animatorSet.start();
屬性動畫插值器值得說的就這麼多(插值器函式中factor的作用、屬性動畫的基本使用),後面會給出完整原始碼。
SpringAnimation實現
Google有專門的一個包用於實現此彈性效果,在gradle指令碼檔案中新增”compile ‘com.android.support:support-dynamic-animation:25.+’”引入此包。這個包的使用也很簡單,這裡給出一個其中一種動畫的實現程式碼:
//建立兩個彈性動畫物件
SpringAnimation springAnimation0 = null;
SpringAnimation springAnimation1 = null;
//指定處理view的哪個屬性,以及view此屬性的最終值(2.0f)
springAnimation0 = new SpringAnimation(imageview, new FloatPropertyCompat<ImageView>("scaleX") {
@Override
public float getValue(ImageView object) {
float scaleX = object.getScaleX();
return scaleX;
}
@Override
public void setValue(ImageView object, float value) {
object.setScaleX(value);
}
}, 2.0f);
springAnimation1 = new SpringAnimation(imageview, new FloatPropertyCompat<ImageView>("scaleY") {
@Override
public float getValue(ImageView object) {
float scaleY = object.getScaleY();
return scaleY;
}
@Override
public void setValue(ImageView object, float value) {
object.setScaleY(value);
}
}, 2.0f);
//作一些設定,要不然肉眼看不出來生效
springAnimation0.setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_ALPHA);
springAnimation1.setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_ALPHA);
//指定此彈性動畫的彈性阻尼
springAnimation0.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY);
//指定此彈性動畫的彈性生硬度
springAnimation0.getSpring().setStiffness(SpringForce.STIFFNESS_VERY_LOW);
//如上
springAnimation1.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY);
springAnimation1.getSpring().setStiffness(SpringForce.STIFFNESS_VERY_LOW);
//啟動動畫
springAnimation0.start();
springAnimation0.start();
需要說的幾個點:
- 此處的彈性動畫只指定了屬性的最終值,而沒有指定屬性的起始值。因為該包會根據當前view的位置自動獲取起始值,所以無需我們指定;
- FloatPropertyCompat,雖然程式碼量看著多,其實不難。建構函式中傳入相關view屬性,兩個抽象方法完成對此屬性的讀寫;
- springAnimation0.setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_ALPHA);在做縮放動畫時,setMinimumVisibleChange方法的呼叫是必須的,如果不呼叫縮放就沒有彈性效果。我也是看了一部分此包的實現原始碼才發現這點的。後面的完整程式碼裡會針對不同的動畫給出不同的setMinimumVisibleChange方法呼叫;
- setDampingRatio,就是設定摩擦力的,摩擦力越大彈起來越費勁,摩擦力越小彈起來越輕鬆;
- setStiffness,這個是設定彈性生硬度的。顯示中彈簧給人的感覺是,如果它鋼性越強彈起來也越費勁鋼性不那麼強的彈起來輕鬆;
- 查了一篇資料,資料中說,dampingRatio(即摩擦力)越大,擺動次數越少,反之則越多;stiffness(即生硬度、鋼性)越大,擺動時間越短,反之則越長。通俗解釋,可感知。
總結
使用插值器實現彈性動畫,最核心的是找到彈性插值器的函式,而此函式已經是前人栽樹後人乘涼了,查資料可以查得;而SpringAnimation的實現,重點是要懂SpringAnimation的基本使用和知道怎麼使用setMinimumVisibleChange使彈性效果肉眼可見。
這裡是完整原始碼