這是 JsonChao 的第279期分享
先上預覽圖:
流程
1.一個勻速圓周運動的點
2.多個勻速圓周運動的點
3.多個圓周運動的點,速度由快到慢
4.點與點之間的間距線性減少,動畫的最後合為一個點
5.為了讓動畫看起來更加流暢,需要在動畫即將結束的時候手動繪製點
核心控件
PathMeasure:截取Path中的一部分並顯示
ValueAnimator:完成動畫從初始值平滑的過渡到結束值的效果,同時還負責管理動畫的播放次數、播放模式、以及對動畫設置監聽器等
先用path畫一個圓
ValueAnimator設置為0f-1f的平滑
用PathMeasure根據ValueAnimator返回的值截取path上的一個點
private Paint mPaint;private Path mPath;private PathMeasure mPathMeasure;private int mWidth,mHeight;private ValueAnimator valueAnimator;//用這個來接受ValueAnimator的返回值,代表整個動畫的進度private float t;
初始化畫筆
初始化Path和mPathMeasure
這裡角度不能選360,否則會測量失誤,具體原因和android的內部優化有關
初始化ValueAnimator
這裡的ValueAnimator設置的是一個時長3秒的動畫,在這3秒中,ValueAnimator會返回一個由0f-1f平滑的數字ValueAnimator.ofFloat(0f,1f).setDuration(3000)在這裡我們用t來接受返回值,同時刷新視圖
t = (float) animation.getAnimatedValue();invalidate();
這裡可以看出t的值,有0到1,這裡就可以把t理解為我們這個動畫的進度
開始繪製
結果圖
我們設置讓t每間隔0.05就畫一個點,總共畫4個點,注意這裡getSegment()的最後一個要設置為true來保證畫出來的是多個點而不是一條線
結果圖
我們先繪製出路程-時間的函數圖像
函數為y = -x*x + 2*x,當x=1時,y=mPathMeasure.getLength();設s = mPathMeasure.getLength();最終我們套用函數:y = -s*x*x+2*s*x;這裡的Y軸代表的是path的長度,X軸對應時間所以把流程二中的y = s*x改成y = -s*x*x+2*s*x即可
結果圖
雖然流程3中點與點的間距已經開始減少,不過這只是因為速度不同間距才改變的,我們的目的是讓這些點到最後合併為1個點,也就是說開始的時候每個點的X間距0.05,結束的時候要讓他們的X相同
目前點之間X的間距函數如下:
我們最後要讓當X=1時,他們的Y值相等,而且他們X的間距由0.05線性平滑到0
看函數圖像已經很清楚了,修改後代碼如下:
結果圖
這裡已經完成了99.9%了,但細心的同學會發現,進度條每次轉動一圈聚成一個點後都會閃一下,這是因為重新開始動畫刷新視圖的原因,這裡的補救方法就是我們在動畫快結束的時候手動畫一個點if(t>=0.95){ canvas.drawPoint(0,-150,mPaint);}
這樣我們就完成了這個進度條
END
往期推薦
這兩年,我打造了一份具備競爭壁壘的 Android 跨平台 通關秘籍
從原理到實戰,全面總結 Android HTTPS 抓包
餓了麼絲滑無縫過度搜索欄的實現
Android Deep Link 深度鏈接,看看你在第幾層?
Android Studio 五分鐘帶你從菜鳥進階到高級調試
點擊下方卡片關注JsonChao,為你構建一套
大廠青睞的 T 型人才系統
▲點擊上方卡片關注JsonChao,構建一套
大廠青睞的 T 型人才知識體系
歡迎把文章分享到朋友圈