看到一個非常炫的載入效果,文章中大佬是透過 css 實現的,今天咱們來用 Android 的自定義 View 來實現一下
這是理想中的效果
這是現實的效果
不能說百分百還原吧,只能說精髓
開工
這個效果仔細看,就是有三個類似月牙形狀的元素進行迴圈轉動,我們只需要拆解出一個月牙來做效果即可,最後再將三個月牙組合起來就可以達到最終效果了
月牙
先畫一個圓
再畫個大一丟丟的
再把這個大圓往右移一丟丟,裁切出來的左右兩個都是月牙
實現
老司機應該一眼就能看出來,只要在兩次繪製圓中只要使用一個疊加模式就能達到裁剪出一個月牙的效果了。那麼是什麼模式呢,我去搜索一下~
噹噹噹,就是它~
PorterDuff。Mode。DST_OUT
相關原始碼如下:
canvas。drawColor(Color。BLACK)val layerId = canvas。saveLayer(0f, 0f, width。toFloat(), height。toFloat(), null, Canvas。ALL_SAVE_FLAG)val halfW = width / 2fval halfH = height / 2fval radius = min(width, height) / 3fpaint。color = Color。WHITEcanvas。drawCircle(halfW, halfH, radius, paint)paint。color = Color。BLACKpaint。xfermode = xfermodecanvas。drawCircle(halfW, halfH - 0。05f * radius, radius * 1。01f, paint)canvas。restoreToCount(layerId)paint。xfermode = null
執行起來我們就得到了一彎淺淺的月牙
立體空間變化
我們可以看出效果圖裡的每一個月牙並不是那麼方正,而是有一定的空間旋轉,再加上繞著 Z 軸旋轉。這裡需要利用 Camera 與 Matrix 實現3D效果(相關知識可參考:https://www。jianshu。com/p/34e0fe5f9e31)
我們先給它在 x 軸轉 35 度 ,y 軸轉 -45 度(參考開頭文章的資料)
rotateMatrix。reset()camera。save()camera。rotateX(35F)camera。rotateY(-45F)camera。getMatrix(rotateMatrix)camera。restore()val halfW = width / 2fval halfH = height / 2frotateMatrix。preTranslate(-halfW, -halfH)rotateMatrix。postTranslate(halfW, halfH)canvas。concat(rotateMatrix)
執行效果如下,從普通的月牙變成了帥氣的劍氣
動畫
我們上面做了固定角度的 X, Y 軸的旋轉,這個時候我們只要加上一個 Z 軸的調轉動畫,這個劍氣就動起來了。
val anim = ValueAnimator。ofFloat(0f, -360f)。apply { // Z 軸是逆時針,取負數,得到順時針的旋轉 interpolator = null repeatCount = RotateAnimation。INFINITE duration = 1000 addUpdateListener { invalidate() }}// 省略前面已寫程式碼。。。camera。rotateZ(anim。animatedValue as Float)// 在合適的地方啟動動畫view。anim。start()
執行效果:
舉一反三
有了這一個完整的劍氣旋轉,只要再來兩道,組成完整的劍氣載入就可以了。
將前面的程式碼抽象成一個方法
private fun drawSword(canvas: Canvas, rotateX: Float, rotateY: Float) { val layerId = canvas。saveLayer(0f, 0f, width。toFloat(), height。toFloat(), null, Canvas。ALL_SAVE_FLAG) rotateMatrix。reset() camera。save() camera。rotateX(rotateX) camera。rotateY(rotateY) camera。rotateZ(anim。animatedValue as Float) camera。getMatrix(rotateMatrix) camera。restore() val halfW = width / 2f val halfH = height / 2f rotateMatrix。preTranslate(-halfW, -halfH) rotateMatrix。postTranslate(halfW, halfH) canvas。concat(rotateMatrix) canvas。drawCircle(halfW, halfH, radius, paint) paint。xfermode = xfermode canvas。drawCircle(halfW, halfH - 0。05f * radius, radius * 1。01f, paint) canvas。restoreToCount(layerId) paint。xfermode = null}
繪製三道劍氣
verride fun onDraw(canvas: Canvas) { super。onDraw(canvas) canvas。drawColor(Color。BLACK) // 偏移角度來源開關文章 drawSword(canvas,35f, -45f) drawSword(canvas,50f, 10f) drawSword(canvas,35f, 55f)}
跑起來看看
Emm。。。 這動畫也太整齊劃一了
錯開三道劍氣
在 Z 軸旋轉上,我們給每道劍氣一個初始值的旋轉值(360/3 = 120),這樣它們就能均勻的錯開了。
相關實現如下:
private fun drawSword(canvas: Canvas, rotateX: Float, rotateY: Float, startValue: Float) { //。。。 省略未改動程式碼 camera。rotateZ(anim。animatedValue as Float + startValue) //。。。 省略未改動程式碼}override fun onDraw(canvas: Canvas) { super。onDraw(canvas) canvas。drawColor(Color。BLACK) drawSword(canvas,35f, -45f, 0f) drawSword(canvas,50f, 10f, 120f) drawSword(canvas,35f, 55f, 240f)}
最終效果
和我們開頭預期的效果圖一模一樣
完整程式碼:https://github。com/samwangds/DemoFactory/blob/master/app/src/main/java/demo/com/sam/demofactory/view/SwordLoadingView。kt
最後
在這裡還分享一份由大佬親自收錄整理的
學習PDF+架構影片+面試文件+原始碼筆記
,
高階架構技術進階腦圖、Android開發面試專題資料,高階進階架構資料
這些都是我現在閒暇時還會反覆翻閱的精品資料。裡面對近幾年的大廠面試高頻知識點都有詳細的講解。相信可以有效地幫助大家掌握知識、理解原理,幫助大家在未來取得一份不錯的答卷。
當然,你也可以拿去查漏補缺,提升自身的競爭力。
真心希望可以幫助到大家,Android路漫漫,共勉!
如果你有需要的話,只需
私信我【進階】即可獲取