此文章来源于星友的提问,关于自定义View一个车机上的音场效果设置,星球提问是免费的,感谢老哥赞赏的鸡腿~,写文章不易,分析原理到实现效果也是要花费一些时间和精力,不过大家加入星球,肯定能学到有用的东西,最起码不用去水群问问题,我的星球有我专门的提问回答区,基本上都能得到满意的答案,欢迎加入我的知识星球【Hi Android】
![f8098f114847fef4207606df5753357d.png](https://i-blog.csdnimg.cn/blog_migrate/d651de2c02a666a998c5bae8965cb2d4.jpeg)
我们要想实现一个效果肯定是要剖析效果图的一些元素,实际上这些喇叭和背景图,都是可以通过后期的布局来实现,那么我们真正实现的,其实是一个固定坐标轴以及圆点的触摸控制,这里可以区别为:背景矩阵(要计算),小红点(实时移动)以及固定的横竖两根,那我们开始吧~
首先绘制横竖两根线条,这个比较简单,通过View的高宽确定坐标轴即可
![74a2ada2c83592c29ef4ef6dcaffebb5.png](https://i-blog.csdnimg.cn/blog_migrate/593e7e7cbcc392e097902eb2e0d6eb77.jpeg)
如果你不太清楚坐标轴的划分的话,这里给你画个图,你应该就清晰了
![dc9fae4b7dd246f60664d8b59890f5b8.png](https://i-blog.csdnimg.cn/blog_migrate/5780ab8a70e05469b760d84649ba6077.jpeg)
我们也可以看到效果图:
![8ce63c361122f1afefde7023d70d2a91.png](https://i-blog.csdnimg.cn/blog_migrate/770b95548545a9ddfcb1d4d99d612c6d.jpeg)
好吧,我们继续,现在绘制一下小红点,小红点绘制起来很简单,这里你可以使用图片,也可以自己绘制圆形,我这里自己绘制一个圆形:
![6ab9159b2d7c5613001fcdc4f591eefe.png](https://i-blog.csdnimg.cn/blog_migrate/82eda262e37dc8b35cecbbac955fb195.jpeg)
圆点的比较直接了,首先我定义了moveX和moveY,因为他会移动,所以这两个也是动态的,而默认则是View的宽高各一半,当然,他的画笔需要设置Style为FILL_AND_STROKE才会填充,那么我们来画图解释一下:
![daf4f4340737590eefdc8d7873be9f5c.png](https://i-blog.csdnimg.cn/blog_migrate/ce334c9ee8c26822fe47b3832a52a2ca.jpeg)
到此,我们就可以看到效果图了:
![bbe632ead47a8ef59d1ba8534d0a256b.png](https://i-blog.csdnimg.cn/blog_migrate/5c458c0e14a80a8098318fdfab572f4a.jpeg)
那么接下来我们就要开始来制定具体的逻辑了;
1.点击View的区域内,红点移动到对应位置
2.根据红点移动的位置,来计算是哪个象限以及计算出喇叭的值
3.通过接口将最终的结果抛出
我们先来实现第一个需求吧,第一个需求不难,只要监听触摸事件即可,我们来看下
![2f2969c317856003aa54e8666bf68b36.png](https://i-blog.csdnimg.cn/blog_migrate/834d2e63119d22ba87dcbdb8af6f9df2.jpeg)
在我们的ACTIon_DOWN中,只要将对应的坐标实时更新,然后刷新View即可办到,如图:
![4fa7c25a8b459a7d4b79f354b1a18c16.png](https://i-blog.csdnimg.cn/blog_migrate/835c768a4c7c20c5ff0b77e1a8eaec1a.jpeg)
但是这里有一个问题,就是因为坐标和中心点会充电,导致有这样一种现象:
![cd6c3dd5f45f7688bb62229c715ba838.png](https://i-blog.csdnimg.cn/blog_migrate/0cac608723de9ca18992fff30bb6ef01.jpeg)
我可以把小圆点移动到一些边边角角上去,这就不好了,那么我们开始优化一下:
![bcf6609ed4052bc37cfe311bc5c3f44c.png](https://i-blog.csdnimg.cn/blog_migrate/48e3d6c56265b9118f30db6412315149.jpeg)
这是优化的代码,优化起来不难,但是你解读起来就需要理解这些绘图的关系了,我们结合画图来分析:
![229028fd411fd31f18c379f319ec12bf.png](https://i-blog.csdnimg.cn/blog_migrate/0d2389adb9379c045ac35cd9e3d5966f.jpeg)
如图所示,我们的左上,右上,左下的逻辑,当然,我们也可以使用拖动小红点来实现一些逻辑,不过没必要,我们继续往下看,根据红点移动的位置,来计算是哪个象限以及计算出喇叭的值。
这里要说一个逻辑,那就是喇叭的阈值为 0 - 20 ,我们现在居中,才是 10,如果我们选择了某一个点,那么他的计算也是不同的,这里我们可以归类一个这样的算法:
1.由于居中才是默认值,都是10
2.移动小红点,四个喇叭都需要修改值
3.我们怎么区分喇叭的值
同样的根据横竖坐标,View的高宽 / 20 即可得到对应值,我们来看图吧,看图就能理解了
![35c3dba3d9ec2c714fd634ca14c0c2cf.png](https://i-blog.csdnimg.cn/blog_migrate/0d90c3ecfe4aeb03a50f9ac6b1fcc960.jpeg)
那么我们现在着手开始实现代码吧:
![f2b30b6bde176e8074214cee88f4e217.png](https://i-blog.csdnimg.cn/blog_migrate/93b02674f761bac0a857d2e63e6a8c95.jpeg)
开开心心实现了这部分代码,然后发现还是有问题的,比如图中的黄色标点,得到的结果是:
喇叭1:16
喇叭2:3
喇叭3:2
喇叭4:17
问题就处在这个喇叭三上,很明显喇叭三其实不可能只有2的,但是根据我们的计算公式 moveY / (viewHeight / 20) 得到的结论又..... 这里我们就发现问题了,不能这样算,而是应该算对角线,我们来看图:
![69c7426f8c5c2e38d2deda90158f2353.png](https://i-blog.csdnimg.cn/blog_migrate/174ba1e63c669107c0d6c98288cb2987.jpeg)
每个象限的计算公式如下,那么我们如何计算呢? 这里可以利用勾股定理来计算三角形斜边,但是在代码中实现有些费尽,我们可以这样来计算,通过两个坐标的x - x与 y - y 即可:
![3ac51ae5e36f0f1371e651e70d45bd2b.png](https://i-blog.csdnimg.cn/blog_migrate/f1939240cab57e95cdac2efe5c1480a4.jpeg)
pow() 方法可返回 x 的 y 次幂的值,利用这个等式我们来计算:
![537ce30bda587d1d9060ea5041898b01.png](https://i-blog.csdnimg.cn/blog_migrate/67b85a96848aeff79663c176380c8eb5.jpeg)
代码生成的图片阅读性不是很好,可以自行下载Demo,我们看到四个象限我们分别进行了计算,并且做了居中的规避,现在我们可以实现我们刚才未实现的第三个步骤通过接口将最终的结果抛出了
定义一个接口
![59db250f013b1de727cfc093b164d485.png](https://i-blog.csdnimg.cn/blog_migrate/bb741d98f8694853af530a32a2d5e562.jpeg)
然后对外抛出,最后的效果:
![a8a408fc614688c34ff36f29954081cb.png](https://i-blog.csdnimg.cn/blog_migrate/239a8ad6fdbb94e1d9a0455128a2dcc6.jpeg)
到此,其实本篇就结束了,这里我的思路还是以矩形为例,实际上正常情况下一般都是正方形,并且绘制好了网格的,相比较而言,绘制View倒是没什么难度,主要是计算这些区域的值,可能颇为麻烦,我也不能保证我这个就是最优的办法,只能说是提供一种思路而已,并且网格的绘制我希望大家自己实现,只需要遍历一下即可,大家自己思考而不是照搬代码,有学习才有进度,好了,相关的PPT和源码可以留言~