可能有點狂了,阿里的offer
還沒拿到手就已經拒了抖音的offer
了,想一想音視頻可能得先放一段落,只能間歇性來更新了,由於最近確實對這方面有點迷茫,交叉面淘系大佬給我列出的知識體系確實過於龐大,我如今仍是得先學着前輩們先把Java
層作好,再進階也不遲。先把精力主戰Java
和Flutter
了。不過以後項目可能儘量會用Kotlin
來作,畢竟這是阿里如今的內部可能主流語言了,畢竟再雲棲大會上登場就是Kotlin
而不是Java
。git
Gtihub傳送門 |
---|
在以前的文章Android自定義View,你摸的透透的了?之中,咱們知道過了View
的繪製流程、過分繪製啊之類的東西。這是基礎,可是如今說的Paint
和Canvas
也是一種很是重要的基礎了,他們用通俗的話來講,就是筆和畫布,而這麼多的繪製哪個任務不是經過他們來完成的呢?github
以前咱們講過音視頻開發,那視頻的概念,其實咱們應該也已經有所瞭解了,就是一幀幀的圖片嘛,繪製的速度超過人眼,那麼就可以演變成視頻了。 面試
上面給出一個貝塞爾曲線的繪製過程,固然這個我已經用代碼實現了。有興趣的讀者能夠直接的去源碼中的
PathView
類中進行查看。canvas
其實我就是模擬了100次而已,可是你就會感受整個圖片他在動,這其實也是動畫實現的一種原理了。ide
這個貝塞爾曲線的模擬,其實能夠分爲幾個部分,兩個相同的部分就是貝塞爾曲線他一條線和一個點的模擬,還有就是中間點,也就是貝塞爾曲線的位置變換模擬了。函數
那在這裏咱們須要注意的地方就來了,如何獲取當前點的位置,顯然咱們只會使用Paint
和Canvas
是遠遠不夠的,由於,咱們的小點顯然須要經過位置變換計算得來的。這裏咱們就要引入咱們一個類Path
了。佈局
Path
Path
,從字面意思咱們就知道,這是一個路徑的意思了。post
先來觀摩一下他的的函數有什麼,和Canvas
可能不同的地方就是,從draw
變到了add
,可是這樣的區別,就能讓Canvas
繪製更加複雜的圖形了,由於draw
的對象都是已經封裝好的圓形、長方形啊等等,而經過add
你就能繪製出各類奇形怪狀的形狀了,而貝塞爾曲線就是他們其中的一份子。學習
PathMeasure
什麼是PathMeasure
呢?其實你關注上方,咱們講過了Path
,可是終究仍是沒講到如何去進行一個位置的計算。而其實這個任務,就是交給咱們的這個PathMeasure
來交接完成的。動畫
fun init(){
pathMeasure = PathMeasure(path, false)
pathMeasure?.length.let {
pathLength = it
mStep = it?.div(INVALIDATE_TIMES)
}
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (pathLength!! >= mDistance!!) {
mDistance?.let { pathMeasure?.getPosTan(it, mPos, mTan) }
mDistance = mStep?.let { mDistance?.plus(it) }
canvas?.drawPoint(mPos?.get(0)!!, mPos?.get(1)!!, paintPoint!!)
invalidate()
}
}
複製代碼
具體代碼仍是須要看我已經完成的PathView
,這裏作一個簡單的介紹,其實這個PathMeasure
經過Path
來計算長度,而後在經過咱們傳入的Distance
來返回當前的Postion
和Tan
值,會有讀者問了Tan
有什麼用,其實通常比較多數的用法就是就是一個角度的調整,若是使用一個點來顯示,確實沒什麼效果,可是若是是一個Bitmap
來現實的,沒有Tan
值,那麼咱們的圖片就不會取轉頭了。
而後經過獲取的Postion
和Tan
值來重繪,咱們就能夠完成咱們的貝塞爾曲線繪製了
以前已經知道了咱們的這個圖片如何去進行繪製,那這個時候咱們就繼續深化了。
首先第一個問題,什麼是刮刮卡?
小二上圖!!!
讀者: cool!!想知道想知道,這個咋實現呀。
小易: 我如今還不想告訴你,嘿嘿。
第二個問題,他有什麼組成部分?
你可能會說,蒙版和底層圖片唄。可是這個答案是,也不是。爲何呢?若是隻有蒙版和底層圖片,其實這個不可以徹底實現的,你可能只能實現到下面的步驟。
一個只能看,不能刮的刮刮卡,哈哈哈哈哈哈哈哈!!!
既然咱們已經說了,這兩個不夠,那確定還有其餘組成成分是須要咱們去進行考慮的了。其實他就是一支筆,這個刮的部分其實他是經過一支筆來完成的。
這裏咱們須要補充幾個知識點了。
經過寫法以下:
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val layerId = canvas?.saveLayer(
null, null
)
canvas?.let { canvasIt ->
paint?.let {paintIt->
rectBitmap?.let { canvas.drawBitmap(it,0f,0f, paintIt) }
paintIt.xfermode = xfermode
circleBitmap?.let { canvas.drawBitmap(it, 50f, 50f,paintIt) }
paintIt.xfermode = null
}
}
layerId?.let { canvas.restoreToCount(it) }
}
複製代碼
經過一個短時的離屏緩衝,來完成兩個圖層的複合來實現。而這個複合就是經過一個layerId
來完成斷定誰和誰是一家人。
這裏又來一個知識點了!!!複合是怎麼實現的???
下面給出一張圖片來解釋,這是Android
內置的Xfermode
,也就是複合模式是如何的,理解圖片的意思便可,也不用專門去學怎麼算的,歸根結底,就是對RGB
某一個色塊的突出或者隱藏。
好了,知道了這幾個知識點,咱們迴歸正題,刮刮卡怎麼實現的問題?咱們知道了複合,知道了離屏繪製,怎麼用呢?
其實最後要討論的就是蒙版是什麼?底層圖片作什麼?
底層圖片天然是給咱們看的,咱們總不能手畫一下,而後被咱們抹掉吧,那這個圖層顯然是不能被咱們的覆蓋掉的。而蒙版呢,咱們須要經過離屏繪製,把圖片和咱們走過的路徑進行重疊消除,來完成看到圖片的效果。那這個效果應該是那種模式來完成呢?咱們看看上面給出的圖片,那個最合適。
刮的過程就是咱們的Dst
和蒙版就是咱們的Src
,這個是應該就是XOR
這個模式是最符合咱們的要求的,咱們繪製過的和Src
重疊的地方所有消去了。
可是看過了源碼的讀者估計會問一個問題,爲何我要建立一個DBitmap
來完成這個任務?其實不實現也能夠的,可是你會出現下圖的狀況了,刮刮卡下方的圖層一片烏漆麻黑,其實這個DBitmap
起到的是一個限制的做用了,給了Paint
的一個做用範圍,那麼實現的就更加舒服了,固然若是你限制了View
在整合佈局中的大小,正好佔滿也是能夠解決這個問題的,可是並不推薦。
最後就是一個簡單的也比較重要的點了,這是Android
的事件分發機制都會問到的一個點,咱們應該重寫什麼方法,來完成繪製路徑的添加。建議仍是在OnTouch
中完成,由於OnTouch
的響應實際上是先於OnTouchEvent
的。
以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。
相關文章推薦: