手把手教你繪制Android粘性果凍動畫組件

從事移動互聯網開發已經快兩年了,回想當初是Android帶我走進了移動端的世界,后來由于自身對用戶體驗比較感興趣,發現iOS更注重對圖形渲染以及動畫處理,所以轉身自學iOS開發,之后也發布了幾個iOS的 組件庫 。但是Android進兩年發展趨勢猛增,在動畫處理上也比以前有所改進,Android3.0之后開啟了GPU硬件加速讓圖形渲染沒以前那么卡頓,特別是5.0之后的material design更是引領潮流。所以趁最近工作不忙有時間,寫了個彈性動畫的 ActionMenu ,核心原理來自咱們iOS界有動畫小王子之稱的kittenyang的 這篇博客 ,廢話不多說了,先上效果圖(gif存在失真,實際效果更佳流暢Q彈)

SpringActionMenu效果圖

1.核心原理

主要知識點其實就下面三項

* Android自定義View以及ViewGroup

* 利用三階貝塞爾曲線繪制圖形

* 通過ValueAnimator結合 阻尼振動 自定義屬性變化

2.各項講解

(1)Android自定義View以及ViewGroup

首先我們先做出一個圓形的彈性動畫效果,先得自定義一個view,然后重寫onDraw可以用過path和paint任意繪制圖形,具體細節我就不多說了,不了解的同學可以查閱相關資料學習。

(2)利用三階貝塞爾曲線繪制圖形

貝塞爾曲線是我認為一個比較神奇的東西,因為他基本上可以繪制出任何圖形,有興趣的同學可以到 這個網站 玩一下,那么我們今天需要做的就是用三階貝塞爾曲線畫圓

三階貝塞爾曲線畫圓

圖中以A,B,C,D四個點作為基準點,把一個圓分4次繪制,以c1-c8作為四次繪制中三階貝塞爾曲線的輔助點,各點的位置我們設為offSet,由前輩們計算,當offSet為(圓形直徑/3.6)時剛好是一個整圓,后來找到一篇 文章 介紹了其原理(雖然我看完之后還是一臉懵逼)。我們設置形變系數為factor(0~1),設定圓形拉伸的最大程度為圓形的2/5, 則extra= circleRadius*2*factor/5,分別列出各點坐標

intxA =0,xB =0,xC =0,xD =0,yA =0,yB =0,yC =0,yD =0;

xA =circleRadius;

xB =circleRadius*2+extra;

xC =circleRadius;

xD =0;

yA =extra;

yB =circleRadius;

yC =circleRadius*2-extra;

yD =circleRadius;

offSet=circleRadius*2/3.6f;

mPath.moveTo(xA,yA);

mPath.cubicTo(xA +offSet,yA,xB,yB  -offSet,xB,yB);

mPath.cubicTo(xB,yB +offSet,xC +offSet,yC,xC,yC);

mPath.cubicTo(xC -offSet,yC,xD,yD  +offSet,xD,yD);

mPath.cubicTo(xD,yD -offSet,xA -offSet,yA,xA,yA);

OK!基本點都繪制完了,直接Run起來

繪制圓形

看到一個紅通通的圓形繪制成功之后第一部大功告成!

(3)通過ValueAnimator結合 阻尼振動 自定義屬性變化

上面我們已經繪制好了一個圓形,接下來事情就很簡單了,只需要通過改變形變系數factor(0~1)的值來改變形變程度就可以了,下面介紹一個Android的動畫API—ValueAnimator,直接通過組件屬性定義的動畫效果,然后重寫變化機制

ValueAnimator valueAnimator = ValueAnimator.ofObject(new FloatEvaluator(time,1,0),1,0);

valueAnimator.addUpdateListener(this);

valueAnimator.setDuration(time);

valueAnimator.start();

@Override

public voidonAnimationUpdate(ValueAnimator animation) {

factor= (float)animation.getAnimatedValue();

invalidate();

}

由此原理就是通過屬性動畫不斷的改變factor從1到0,然后刷新重繪小圓球,FloatEvaluator就是我們自定義的根據什么樣的函數去改變factor,這個時候就要介紹到我們高中學習的 阻尼振動 函數了

阻尼振動

阻尼振動

該函數可以模擬最真實的彈性效果

阻尼振動函數

我們60幀為基準(肉眼看到刷新流暢度的最低標準),計算出一列變化factor的值

publicFloatEvaluator(longtime, floatstartValue, floatendValue) {

sum= (int)time *60/1000;

float diff = endValue - startValue;

value=new float[sum];

float x;

for(int i = 0; i < sum; i++) {

x = i *1.0f/sum;

value[i] = endValue - (float)(diff * Math.pow(Math.E,-1*dampingFactor* x) * Math.cos(velocityFactor* x));

}

}

其中dampingFactor和velocityFactor為阻力和速度,我這里設置的是5和30,可以自定義調節改變彈性程度。

基本構建完成,添加一個按鈕啟動動畫試試效果

彈性動畫效果圖

大功告成!

3.總結

大家掌握了一個圓形組件的形變原理之后剩下的就容易多了,利用ViewGroup多繪制幾個擺擺位置就OK了,也可以利用這種原理自己創新構思出別的控件,只要掌握了核心的兩點:

1.貝塞爾曲線繪制圖形

2.利用阻尼函數以及ValueAnimator自定義形變屬性的值

 

 

 

 本文由用戶 KatMHE 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!