用drawRect的方式实现一个尺子

用drawRect的方式实现了一个尺子选择器,demo在这里:https://github.com/Phelthas/LXMRulerView
效果如图:
 
如果不考虑复用的问题,我感觉最简单的实现方式其实是让美术做一张尺子的图片,放到scrollView上就可以了,
数值可以根据scrollview的contentOffset来计算。
如果考虑复用的问题,还是用代码写来的方便,封装一些属性,就可以实现很多不同的样式。所以就有了这个LXMRulerView~
 
实现方案:
目前用的是一个比较笨的实现方案,就是用drawRect的方式画了一个尺子,然后把这个view放到scrollview上,然后用scrollview的contentOffset来计算数值。
有看到资料说用drawRect的方式会比较占内存,用CALayer实现会好很多,这个我还没有试,但目前来看demo里面内存占用都很小,有空试一下layer的实现方式吧~
为什么说这个方案比较笨呢?因为这里面其实是完完全全画了一个完整的尺子,没有复用任何资源,所以理论上如果尺子很长很长的话,还是会很消耗内存的;
考虑到尺子也是不断重复的外观,只有数字不一样,所以理论上用一个横向的collectionView来实现会更好一些,这个有空实践一下看看效果怎么样吧~
 
 
需要注意的地方:
1,对autoLayout的支持和从xib初始化的支持
drawRect是按bounds来画图的,而且默认情况下drawRect方法只会调用一次。
所以如果从xib初始化,且初始化时的view大小与最终显示的view大小不同的话,drawRect是按最初初始化的大小来绘制的,不会随着autoLayout调整大小,
所以这里没有什么好的办法,只能在layoutSubview中手动调整改view的大小。
但仅仅调整view大小还不够,画好的图默认不会重新绘制,UIView有一个contentMode属性,需将其设置为UIViewContentModeRedraw,
效果是在view的bounds有变化时,会重新调用drawRect方法。
 
2,整数吸附效果
在scrollviewDidScroll的方法中调整contentOffset来使其停留在整数的位置上的方法太low了!!!会使动画效果看起来很不连贯
怎么解决呢?
就是用
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint *)targetContentOffset
这个方法,这也是系统提供的delegate方法,所以可以放心用,效果就是可以让scrollview刚好停留在targetContentOffset的位置,所以只需要在这个方法中计算出指定的位置就可以了~
 
3,数值变化的回调
为了简单易用,数值变化的回调方法是用block的方式。
在用的时候,需要注意一下循环引用的问题,所以block中还是用weakSelf安全一点
 
4,为了保证滑动位置的准确度,尺子最大最小值和间距都只支持整型,不支持浮点数~~等想到好解决办法支持~
 
 
2016年9月28日更新
经测试发现,如果尺子比较长的话,用drawRect的方式确实占用了很大的内存,而且尺子越长,占用的内存越大,所以改用CALayer的方式实现,可以有效的减少内存;
加入了accuracy属性,表示一个刻度代表的值,比如accuracy为0.1,那么一个刻度表示0.1; 
 
2017年3月25日更新
因为在tableView的cell中使用了这个rulerView,发现每次reloadData的时候界面都会卡很久,想来估计还是尺子在绘制的时候卡住了。。。
被逼无奈,还是只能用collectionView重构一下了,也就是最开始写的时候就想到但是没有实践的方式。。。
重构效果还不错,现在就算是在tableViewCell里,也能瞬间绘制完成了;
加入了defaultValue属性,让尺子可以在绘制完成时直接显示设定的值:
这里稍微有点坑需要注意一下,因为scrollview在调整contentInset的时候,触发ScrollViewDidScroll方法,所以要注意设置初始值的时机,目前我是写在layoutSubView方法里面的;
pod已经更新到2.1.0版本,欢迎使用~ 
 
目前还在持续更新中,有什么问题欢迎讨论~
 
 
posted @ 2016-07-22 21:19  Phelthas  阅读(796)  评论(1编辑  收藏  举报