4.初始化默认显示的item的position,即选中项位置
由于我们在onDraw方法里面,translateY和scaleY都是是通过弧度 α 计算得到的,因此需要从弧度α开始入手。
由计算公式 α = L / R 可知,我们若要得到某项Item的弧度,则需要知道弧长和半径,半径之前我们已经同计算获取到了值,所以现在需要计算弧长。
弧长L = itemHeight * counter - itemHeightOffset;
即 Item的高度乘以该项Item所在Position位置,再减去已滑动距离的偏移量(itemHeightOffset < itemHeight ),计算出了弧长L,则可计算出每项Item对应的弧度α,计算出了α之后,根据三角函数可计算出平移距离translateY,如下图 :
“等等,大兄弟,刚刚不是说‘scaleY = cosα ’吗”,怎么缩放文字的代码是这样的:
canvas.scale(1.0F, (float) Math.sin(radian));
别急别急,这是由于为了使Item的显示位置处于第一象限及第四象限,我们把半圆以Y轴为轴心向右转90度了。所以我们的角度 angle = (float) (90D - (radian / Math.PI) * 180D);(使角度的取值范围为[-90°, 90°])
1.弧度和角度转换公式 α = angle*π/180
2.正弦和余弦转换公式 cosα = sin( π/2-α )
我们就把cos函数 给转化成sin函数了。
4.文字自适应大小
由于item的文字长度是不固定的,所以会存在文字长度过长而导致绘制超过Wheelview的宽度,因此这里需要做一下处理,当文字长度超过measuredWidth的时候,重设字体大小让其能完全显示:
一次静态图形绘制完成了,但是我们需要根据滑动距离让item文字动态地变换,以达到需求,那么如何根据滑动距离来控制UI变化呢?
别着急,之前已经说了定义WheelView 的时候需要覆盖onTouchEvent方法,必然是有它的道理的。我们通过onTouchEvent方法,然后:
分别处理MotionEvent.ACTION_DOWN、ACTION_MOVE、ACTION_UP 这三个事件,获取到滑动距离并记录下来。
根据获取的滑动距离、计算停止滑动时item所需要的偏移量 ,边界处理等工作。
最后调用invalidate()方法通知系统更新UI,相当于重新调用了onDraw()方法,重新绘制UI,实现3D滚轮效果。
由于篇幅问题,就只贴一下部分关键代码了:
以上是WheelView的实现原理以及绘制过程的讲解,但是实际使用中我们往往需要多个Wheelview 并设置联动来实现我们的功能,所以Android-PickerView,这个项目就是对其进行了很好的封装,提供了两种选择器,一种是时间选择器(timePicker),一种是选择选择器(optionPicker)。