用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图

大家好,可能今年换了公司过得比较安逸,自己的心情也不算太好,所以一段时间都没很好的学习和更新文章。自从最近看了扔物线HenCoder的文章之后,自己感觉自己对很多自定义View和动画的知识都不太懂,甚至在平时的开发极少用到,所以自己想好好学习这一块的知识。之前无意中在公众号上看到一个仿英雄联盟的的七边形战力图,自己发现,平时我看的好几个app都有这样的多边形战力图,所以觉得可以自己做一个大众版的出来,适配各个关于多边形战力图的自定义View。下面我们看看效果图:

用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第1张图片
掌上英雄联盟和懂球帝的效果图.png

然后再看看我自己写的自定义View的效果:
用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第2张图片
我自己写的View效果图.png

可以看到其实大致的效果是差不多的,但是有一些小细节可能需要自己去定制某个条件再处理,细化和润色,因为我这里是用同样的方法,只是设置的参数不一样,所以看上去有些细节需要再根据自己是几边形再调整一下。
大家看看我写的代码就知道了:
用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第3张图片
配置代码.png

只需要短短的代码就能画出不同的战力多边形。
好的,那下面我们就来讲讲这个东西是怎么实现的,老规矩,如果不想听分析的同学可以直接下载源码去看看。 源码下载链接
讲代码之前,先给大家讲一下画出这个多边形的原理,对,就是数学原理,先看看下面的图:
用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第4张图片
原理图.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写代码写项目。一开始确实很不习惯,速度很慢,但是我觉得我总会熟能生巧的吧,所以贵在坚持嘛。
下面我们以懂球帝的六边形战力图为例一步步画出想要的效果吧:

一、首先我们需要画出一个多边形,和嵌套的多个多边形。

用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第5张图片
首先我们需要画出一个多边形,和嵌套的多个多边形.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,那是因为我们需要把六边形旋转一下,视觉效果更好。


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第6张图片
一个六边形.png

一个六边形我们画出来了,那么一个六边形里面多个嵌套的多边形就能很容易的画出来了,只需要在第一个for循环的外面再加一个for循环,每次把半径都减去一定的值,那很简单就画出来了。在上图中红色框框外的代码做的事情就是去加一个for循环,和给画笔paint加上一些图片的填充颜色,另外还在六边形描了画边。


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第7张图片
多边形嵌套.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()))

这句代码就是把我们所要画的六边形的六个点的坐标保存了下来,为方便我们之后用,而且下面很多地方都用到了,你看,这里就用到了。


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第8张图片
画角边.png

我们这里考虑到有些多边形不需要角边,所以加了一个判断,不需要就设置false就好了。


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第9张图片
画角边图.png

画完角边我们就考虑一下多边形外面的字体了。

三、画出字体

用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第10张图片
画出字体代码.png

老实说,这里是我做这个自定义View最难受的地方,因为字体的位置要根据六边形每个角慢慢调整字体的不同的位置,我没想到更好的办法处理,暂时只是按照坐标轴的四个象限来稍微调整了一下位置,所以当每个同学有兴趣做定制化的时候,需要自己再做一些细节的字体位置调整处理。


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第11张图片
画出字体图.png

画完六边形外面的内容,那么我们就要往里看看了吧。

四、画出分数区域及设置相关属性

1.我们要设置分数区域的一些属性,另它更好看一点:


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第12张图片
设置分数区域属性.png

2.设置各个属性的分数比例:


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第13张图片
设置各个属性的分数比例.png

3.按比例画出每个区域的点并连成线:
用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第14张图片
按比例画出每个区域的点并连成线.png

其实这一步跟第一步很类似,也并没有什么难点可言。
最后我们来看看最终的效果图:


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第15张图片
最终的效果图.png

讲完多边形战力图的原理代码,我们再看看要如何使用:
用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第16张图片
使用图.png

关于使用,我用了设计模式的builder模式,即建造者模式来管理整个自定义View的配置。我把每个属性都分开做定制化处理,并连成一条数据链初始化,然后最后调用build的方法就可以实现所有方法的配置,是不是很简便,虽然代码量多了,但是builder模式对我以后对这个自定义View的修改和扩展非常有好处。
下面讲讲做这个自定义View在kotlin上遇到的一些小问题:
1.构造函数的编写跟java有区别:
用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第17张图片
构造函数的编写跟java有区别.png

有人注意到了吗,虽然在意思上是一样的,但是kotlin和java在表达上在构造函数这块上可有不一样的地方。

2.kotlin的小坑:

谁都知道,kotlin是不需要在代码中初始化xml控件的,这一点用过的人都会觉得很方便,但是在这里我踩了一个小坑,看下图:


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第18张图片
kotlin初始化.png

用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第19张图片
kotlin_xml.png

大家是不是会觉得这段代码完全没问题?我一开始也是这么认为的,但是我得到的结果是。。。。。


用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第20张图片
image.png

为什么说我没有初始化呢,明明代码的编译成功了,我一开始想不明白为什么,后来经过一个师兄的提醒 ,我才发现我们在声明的时候,dongqiudiPolygonView指向的只是一个int类型的数字,但是如果你想用他的build方法,你还是要老老实实的加上一句
dongqiudiPolygonView = findViewById(R.id.dongqiudiPolygonView)

用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图_第21张图片
findViewById.png

哎,坑啊,所以说探索还是需要有点代价的,下次就不会再犯这种低级错误了。
好了,这一期就讲得差不多了,如果对我的代码有什么建议的同学可以跟我讨论一下,譬如说很多kotlin的问题我自己都没搞得懂~对我的项目有兴趣的同学可以下载我的源码一起学习和交流,共同进步! 源码下载链接

你可能感兴趣的:(用Kotlin画起仿掌上英雄联盟和懂球帝的自定义多边形战力图)