大家好,可能今年換了公司過得比較安逸,自己的心情也不算太好,所以一段時間都沒很好的學習和更新文章。自從最近看了扔物線HenCoder的文章之後,自己感覺自己對很多自定義View和動畫的知識都不太懂,甚至在平時的開發極少用到,所以自己想好好學習這一塊的知識。之前無意中在公眾號上看到一個仿英雄聯盟的的七邊形戰力圖,自己發現,平時我看的好幾個app都有這樣的多邊形戰力圖,所以覺得可以自己做一個大眾版的出來,適配各個關於多邊形戰力圖的自定義View。下面我們看看效果圖:
![掌上英雄聯盟和懂球帝的效果圖.png](https://i.iter01.com/images/af54d2f84fce9fdb2afe9304a967c8ed093e0b04a9e6ceb273ce834fc4d9838f.png)
![我自己寫的View效果圖.png](https://i.iter01.com/images/b9f6b522ce1928321718266431f01f19661d3cd1365efe7f938f97bd32fdce49.png)
大家看看我寫的程式碼就知道了:
![配置程式碼.png](https://i.iter01.com/images/2924333ae9893eb1b1715b68586b8e89dc0fcb3e4aaa3a528f3ca66f12a6b72b.png)
![原理圖.png](https://i.iter01.com/images/5879334bd659e91541105a7e3ab4360e920cfecd5c6e54767066d562782fd215.png)
用一個正六邊形舉例,假設說它每個角到座標原點為半徑X,那麼我們用數學的原理XcosA就能得出得出B點的X軸座標,XsinA能得出B點的Y軸座標,由此我們看出來B(XcosA,XsinA),至於∠A的度數怎麼來的就更簡單了,正n邊形360°/ n,即 2π/n 就能得到一個角是多少度的了。那很自然而然的,我們用一個for迴圈就可以得出六邊形所有的座標點
for (i in 0..count - 1) {
//每個座標點
(radius * cos(2 * Math.PI / count * i)).toFloat(), (radius * sin(2 * Math.PI / count * i)).toFloat())
}
複製程式碼
以上就是多邊形戰力圖的數學原理,應該很簡單吧。其實很多自定義View也是一樣,只要懂了原理,很多東西很自然而然很簡單的就能寫出來。生活上很多事情也是一樣,沒做之前什麼事情都想著自己做不好就放棄了,但是自己嘗試了發現原來這個事情原來那麼簡單,我每次寫自定義View總有這個感慨。
不吹什麼了,確實畢業一年多工作兩年最近感慨有點。好了,下面我們來看看程式碼我是怎麼一步步實現的吧。在實現程式碼之前,我先說這個View我是用kotlin寫的,最近也慢慢用kotlin寫程式碼寫專案。一開始確實很不習慣,速度很慢,但是我覺得我總會熟能生巧的吧,所以貴在堅持嘛。 下面我們以懂球帝的六邊形戰力圖為例一步步畫出想要的效果吧:
一、首先我們需要畫出一個多邊形,和巢狀的多個多邊形。
![首先我們需要畫出一個多邊形,和巢狀的多個多邊形.png](https://i.iter01.com/images/3391122c4518490d9ab2eb3a2f8c563197d6b3bbe44bfd747d0aee97317231af.png)
程式碼很簡單,我們看看紅色框裡面的程式碼就是最核心的部分,一個for迴圈,剛剛講原理的時候也說過。那下面詳細分析一下,當i=0的時候,我們把path移動到我們的第一個點上,
path.moveTo((radius * cos(2 * Math.PI / count * i - Math.PI / 2)).toFloat(), (radius * sin(2 * Math.PI / count * i - Math.PI / 2)).toFloat())
複製程式碼
當i>0的時候,我們就需要把這些點用路徑直線連起來了,所以用的是lineTo()
path.lineTo((radius * cos(2 * Math.PI / count * i - Math.PI / 2)).toFloat(), (radius * sin(2 * Math.PI / count * i - Math.PI / 2)).toFloat())
複製程式碼
有人會問為什麼角度最後需要減去π / 2,那是因為我們需要把六邊形旋轉一下,視覺效果更好。
![一個六邊形.png](https://i.iter01.com/images/dc548f4d582c7e0fe911a1a66c783809cc47271386c2e609b5cffc46430d588d.png)
![多邊形巢狀.png](https://i.iter01.com/images/d314a5cafd31600b3f100698f4de176fc35b5d619bd5004cf3884a52426ecedb.png)
二、畫六邊形的中心到每個角的角邊:
有人注意到了嗎,我們在第一個for迴圈的時候加了一句程式碼:
//把相應的點儲存到pointList中
points.add(PointF(radius * cos(2 * Math.PI / count * i - Math.PI / 2).toFloat(), radius * sin(2 * Math.PI / count * i - Math.PI / 2).toFloat()))
複製程式碼
這句程式碼就是把我們所要畫的六邊形的六個點的座標儲存了下來,為方便我們之後用,而且下面很多地方都用到了,你看,這裡就用到了。
![畫角邊.png](https://i.iter01.com/images/1041e5255999930ef8630f8448d78cda96f0465ae3c9c1d65d3c93b3dd674378.png)
![畫角邊圖.png](https://i.iter01.com/images/7bbcb008ddc497642ae0d0e7d47966556a38d60af1da6faad5b0d43017052fe8.png)
三、畫出字型
![畫出字型程式碼.png](https://i.iter01.com/images/c2a77d269172a265d4b0c06f02c87e030583cb63802ddfc6d0fe0022bb12b22c.png)
![畫出字型圖.png](https://i.iter01.com/images/f996e83f9ec6bd09540808020ce0de60be0686bb4cb1c0581db22d95dd7e3128.png)
四、畫出分數區域及設定相關屬性
1.我們要設定分數區域的一些屬性,另它更好看一點:
![設定分數區域屬性.png](https://i.iter01.com/images/d0c3d1bd6d1b8e66d390ca8ba905d1e5ca24b293200051fcbec4fa983f1bb614.png)
![設定各個屬性的分數比例.png](https://i.iter01.com/images/838eca7a625c268b90e8c0447181af3be2c48290f4bc17ff86433b753838b15a.png)
![按比例畫出每個區域的點並連成線.png](https://i.iter01.com/images/e008c40aec31a7b45a23416854526b7370151a8022943465bc39c0841d5d25c9.png)
![最終的效果圖.png](https://i.iter01.com/images/46e74e4b556641c0c7d8ec1142fabf27b387ef3c8988bea46d75f9f2bd4abeb1.png)
![使用圖.png](https://i.iter01.com/images/1a7d296b3f15ab7e70028fd57f8dd094152a0aadb1b911425713720ceffe5343.png)
下面講講做這個自定義View在kotlin上遇到的一些小問題:
1.建構函式的編寫跟java有區別:
![建構函式的編寫跟java有區別.png](https://i.iter01.com/images/3231e0c770ddc9da27e21ff2091876c2ed2eb0d612571d39c6d908970497780d.png)
2.kotlin的小坑:
誰都知道,kotlin是不需要在程式碼中初始化xml控制元件的,這一點用過的人都會覺得很方便,但是在這裡我踩了一個小坑,看下圖:
![kotlin初始化.png](https://i.iter01.com/images/f4c90334d83277dc6b6faaada8937a58c0458c84d1de62f796d6924c9ebf8434.png)
![kotlin_xml.png](https://i.iter01.com/images/9052bb0e20dccd72dbcc40b8fe45d3f47ec34215b6139ed91d8c8a30d98de8fb.png)
![image.png](https://i.iter01.com/images/8aed30bcb1cb21b3a8a57fa9da7502cfd0a46926f770b2c0b6615fff3f8b90e1.png)
dongqiudiPolygonView = findViewById(R.id.dongqiudiPolygonView)
複製程式碼
![findViewById.png](https://i.iter01.com/images/bbff97bb8b9f2f1bcdb42167c87ec78bd8122e1ac4c93b8d74f54e171bbe0af3.png)
最近在簡書感覺漸漸沒人看了,所以第一次在掘金髮布文章,如果大家想看我的文章,我可以把那邊的文章遷移到這邊來。 我的簡書