工作是做运动方面的app,所以会经常关注一些运动类的app,去年的时候在《格瓦拉运动》上看到一个控件,感觉挺有意思的。因为时间的原因,没有去深入研究。
这阵子时间稍微空闲点,再去看了下,忽然发现格瓦拉运动服务器都已经关停了,还好,app还能下载,控件效果还是可以看到的
好了,那么,先上效果图:
主要的功能和效果大概如此,其他的便是细节之处的雕琢了。这个,就交给各位了吧~
(由于控件的代码相对来说有点多,这里只是讲解一下写的思路了,代码放在文末,可点击下载)
1.难点分析
那么,我们来对这个控件分析一下。
1.首先,我们可以看到的是,控件上的子view是以弧形的方式分布的,并且,每个子view之间的间隙也是一定的。
2.通过图片我们可以发现,控件是左右滑动的,并且,向左右滑动时无限循环的。
3.控件的位置是固定的,无论是点击滑动,或是手动左右滑动,图上的控件总是在固定的位置。并且,如果各位下原版app的话可以看到,手势滑动之后,停下之后还会抖动一下,再回到原来的位置。
4.由图可以看到,子view在靠近中间时,会变大,离开时会变小。
这几点我们可以通过对控件的查看得知。那么,接下来,便是逐一的对各个难点进行攻破了。
2.难点解析
1.弧形
提到弧形,我们首先想到的可能是圆,并且,在观察控件时,这一条弧线很像是圆上的一段。(实际上可能更像是椭圆上的一段,但是,在开始时一直按圆考虑的,所以,还是当成圆吧)
把弧形轨迹看成圆上的一段的话,那么,圆上的子view,我们就可以看成是圆上的一点了。
继而我们可以分解成,圆上的一点绕圆运动。
OK,分析到了这里,相信部分读者可能想到了第一点的解决方案。
一个点,以圆形轨迹来运动。
2.多点分布
我们可以看到,屏幕上的子view是固定5个的。
那么,我们可以把他当成圆上的五个点,按照一定的间隔分布。
那么,子view的x坐标其实是可以确定的,唯一需要确定的是Y坐标,但是,作为圆上一点,y轴其实是可以通过公式计算的。
centY = CentY + (int) Math.sqrt(Math.pow(RADIUS, 2) - Math.pow((centX - CentX), 2));
其中cenY是子view的坐标,CentY是圆的Y坐标,CentX是圆的X坐标,RADIUS则是圆的半径。
3.无限循环
这点其实也是也是比较好计算的,这里我的思路是,在初始化的时候,选择一个leftView和RightView作为标志,用他们来判断左右是否还有控件。
如果leftView滑动到了屏幕的第二个view的位置,那么将rightview放在最左边。
如果rightView滑动到了屏幕的第四个位置,那么将leftview放在最右边。
这样,就可以达到无限循环了
4.滑动位置固定在五个点。
这里我的做法是,每次滑动结束的时候,都会去resetView一次,即重置view的位置,在这里计算出一个view距离他正确位置的差距,然后,进行移动。
5.滑动时大小变动
这个其实也是很容易的,我的做法是将view的位置和中心点进行判断,如果靠近中心点,那么就变大,远离则变小。当然,只对,中间的三个view进行了判断。
6.点击和滑动事件的添加。
点击事件是通过对按下的坐标和松开的坐标来进行判断的。
滑动事件则在左右滚动结束之后响应。
7.手势滑动
这里稍微偷了一下懒,根据VelocityTracker类对滑动速度进行了判断,并进行了简单的处理,如果用力滑动之后,那么会有加速度,然后缓慢停下。
好啦,以上大概是我在写这个控件的一些思考点吧,大家如果有什么疑惑的话,可以在评论区留言,我会一一解答的。
项目已上传到Github, 点击下载
博客所有项目都会上传到github,如果觉得还不错的话,可以关注下,最好git给个star了~~~