.h文件
// // SXSRulerControl.h // SXSInvestScaleSlider // // Created by Angela on 16/9/26. // Copyright © 2016年 iaiai. All rights reserved. // #import IB_DESIGNABLE //轻量级标尺控件 @interface SXSRulerControl : UIControl @property (nonatomic, assign) IBInspectable CGFloat selectedValue;//选中的数值 @property (nonatomic, assign) IBInspectable NSInteger minValue;//最小值 @property (nonatomic, assign) IBInspectable NSInteger maxValue;//最大值 @property (nonatomic, assign) IBInspectable NSInteger valueStep;//步长 @property (nonatomic, assign) IBInspectable CGFloat minorScaleSpacing;//小刻度间距,默认值 `8.0` @property (nonatomic, assign) IBInspectable CGFloat majorScaleLength;//主刻度长度,默认值 `40.0` @property (nonatomic, assign) IBInspectable CGFloat middleScaleLength;//中间刻度长度,默认值 `25.0` @property (nonatomic, assign) IBInspectable CGFloat minorScaleLength;//小刻度长度,默认值 `10.0` @property (nonatomic, strong) IBInspectable UIColor *rulerBackgroundColor;//刻度尺背景颜色,默认为 `clearColor` @property (nonatomic, strong) IBInspectable UIColor *scaleColor;//刻度颜色,默认为 `lightGrayColor` @property (nonatomic, strong) IBInspectable UIColor *scaleFontColor;// 刻度字体颜色,默认为 `darkGrayColor` @property (nonatomic, assign) IBInspectable CGFloat scaleFontSize;//刻度字体尺寸,默认为 `10.0` @property (nonatomic, strong) IBInspectable UIColor *indicatorColor;//指示器颜色,默认 `redColor` @property (nonatomic, assign) IBInspectable CGFloat indicatorLength;//指示器长度,默认值为 `40.0` @property (nonatomic, assign) IBInspectable NSInteger midCount;//几个大格标记一个刻度 @property (nonatomic, assign) IBInspectable NSInteger smallCount;//一个大格里面几个小格 @end
.m文件
// // SXSRulerControl.m // SXSInvestScaleSlider // // Created by iaiai on 16/9/26. // Copyright © 2016年 iaiai. All rights reserved. // #import "SXSRulerControl.h" #define kMinorScaleDefaultSpacing 20 // 小刻度间距 #define kMajorScaleDefaultLength 25.0 //主刻度高度 #define kMiddleScaleDefaultLength 17.0 //中间刻度高度 #define kMinorScaleDefaultLength 10.0 //小刻度高度 #define kRulerDefaultBackgroundColor ([UIColor clearColor]) //刻度尺背景颜色 #define kScaleDefaultColor ([UIColor lightGrayColor]) //刻度颜色 #define kScaleDefaultFontColor ([UIColor darkGrayColor]) //刻度字体颜色 #define kScaleDefaultFontSize 10.0 //刻度字体 #define kIndicatorDefaultColor ([UIColor redColor]) //指示器默认颜色 #define kIndicatorDefaultLength 80 //指示器高度 @interface SXSRulerControl () @end @implementation SXSRulerControl{ UIScrollView *_scrollView; UIImageView *_rulerImageView; UIView *_indicatorView; } #pragma mark - 构造函数 - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupUI]; } return self; } - (void)layoutSubviews { [super layoutSubviews]; if (_rulerImageView.image == nil) { [self reloadRuler]; } CGSize size = self.bounds.size; _indicatorView.frame = CGRectMake(size.width * 0.5, size.height - self.indicatorLength, 1, self.indicatorLength); // 设置滚动视图内容间距 CGSize textSize = [self maxValueTextSize]; CGFloat offset = size.width * 0.5 - textSize.width; _scrollView.contentInset = UIEdgeInsetsMake(0, offset, 0, offset); } #pragma mark - 设置属性 //指示器颜色 - (void)setIndicatorColor:(UIColor *)indicatorColor { _indicatorView.backgroundColor = indicatorColor; } ////选中的数值 - (void)setSelectedValue:(CGFloat)selectedValue { if (selectedValue <</span> _minValue || selectedValue > _maxValue || _valueStep <= 0) { return; } _selectedValue = selectedValue; [self sendActionsForControlEvents:UIControlEventValueChanged]; CGFloat spacing = self.minorScaleSpacing; CGSize size = self.bounds.size; CGSize textSize = [self maxValueTextSize]; CGFloat offset = 0; // 计算偏移量 CGFloat steps = [self stepsWithValue:selectedValue]; offset = size.width * 0.5 - textSize.width - steps * spacing; _scrollView.contentOffset = CGPointMake(-offset, 0); } #pragma mark - UIScrollViewDelegate - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { CGFloat spacing = self.minorScaleSpacing; CGSize size = self.bounds.size; CGSize textSize = [self maxValueTextSize]; CGFloat offset = targetContentOffset->x + size.width * 0.5 - textSize.width; NSInteger steps = (NSInteger)(offset / spacing + 0.5); targetContentOffset->x = -(size.width * 0.5 - textSize.width - steps * spacing) - 0.5; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (!(scrollView.isDragging || scrollView.isTracking || scrollView.isDecelerating)) { return; } CGFloat spacing = self.minorScaleSpacing; CGSize size = self.bounds.size; CGSize textSize = [self maxValueTextSize]; CGFloat offset = 0; offset = scrollView.contentOffset.x + size.width * 0.5 - textSize.width; NSInteger steps = (NSInteger)(offset / spacing + 0.5); CGFloat value = _minValue + steps * _valueStep/(_midCount*_smallCount); if (value != _selectedValue && (value >= _minValue && value <= _maxValue)) { _selectedValue = value; [self sendActionsForControlEvents:UIControlEventValueChanged]; } } #pragma mark - 绘制标尺相关方法 - (void)reloadRuler { UIImage *image = [self rulerImage]; if (image == nil) { return; } _rulerImageView.image = image; _rulerImageView.backgroundColor = self.rulerBackgroundColor; [_rulerImageView sizeToFit]; _scrollView.contentSize = _rulerImageView.image.size; // 水平标尺靠下对齐 CGRect rect = _rulerImageView.frame; rect.origin.y = _scrollView.bounds.size.height - _rulerImageView.image.size.height; _rulerImageView.frame = rect; // 更新初始值 self.selectedValue = _selectedValue; } - (UIImage *)rulerImage { // 1. 常数计算 CGFloat steps = [self stepsWithValue:_maxValue]; if (steps == 0) { return nil; } // 水平方向绘制图像的大小 CGSize textSize = [self maxValueTextSize]; CGFloat height = _scrollView.frame.size.height-_rulerImageView.frame.size.height ; CGFloat startX = textSize.width; CGRect rect = CGRectMake(0, 0, steps * self.minorScaleSpacing + 2 * startX, height); // 2. 绘制图像 UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0); // 1> 绘制刻度线 UIBezierPath *path = [UIBezierPath bezierPath]; for (NSInteger i = _minValue; i <= _maxValue; i += _valueStep) { // 绘制主刻度下 CGFloat x = (i - _minValue) / _valueStep * self.minorScaleSpacing * (_midCount*_smallCount) + startX; [path moveToPoint:CGPointMake(x, height)]; [path addLineToPoint:CGPointMake(x, height - self.majorScaleLength)]; // 绘制主刻度上 [path moveToPoint:CGPointMake(x, 0)]; [path addLineToPoint:CGPointMake(x,self.majorScaleLength)]; if (i == _maxValue) { break; } // 绘制小刻度线下 for (NSInteger j = 1; j < (_midCount*_smallCount); j++) { CGFloat scaleX = x + j * self.minorScaleSpacing; [path moveToPoint:CGPointMake(scaleX, height)]; CGFloat scaleY = height - ((j%_smallCount == 0) ? self.middleScaleLength : self.minorScaleLength); [path addLineToPoint:CGPointMake(scaleX, scaleY)]; } // 绘制小刻度线上 for (NSInteger j = 1; j < (_midCount*_smallCount); j++) { CGFloat scaleX = x + j * self.minorScaleSpacing; //上 [path moveToPoint:CGPointMake(scaleX, 0)]; CGFloat scaleY =((j%_smallCount == 0) ? self.middleScaleLength : self.minorScaleLength); //上 [path addLineToPoint:CGPointMake(scaleX, scaleY)]; } } [self.scaleColor set]; [path stroke]; // 2> 绘制刻度值 NSDictionary *strAttributes = [self scaleTextAttributes]; for (NSInteger i = _minValue; i <= _maxValue; i += _valueStep) { NSString *str = @(i).description; CGRect strRect = [str boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:strAttributes context:nil]; strRect.origin.x = (i - _minValue) / _valueStep * self.minorScaleSpacing *( _midCount*_smallCount) + startX - strRect.size.width * 0.5; strRect.origin.y =_scrollView.frame.size.height*0.5-textSize.height*0.5; [str drawInRect:strRect withAttributes:strAttributes]; } UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return result; } - (CGFloat)stepsWithValue:(CGFloat)value { if (_minValue >= value || _valueStep <= 0) { return 0; } return (value - _minValue) / _valueStep *( _midCount*_smallCount); } - (CGSize)maxValueTextSize { NSString *scaleText = @(self.maxValue).description; CGSize size = [scaleText boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:[self scaleTextAttributes] context:nil].size; return CGSizeMake(floor(size.width), floor(size.height)); } - (NSDictionary *)scaleTextAttributes { CGFloat fontSize = self.scaleFontSize * [UIScreen mainScreen].scale * 0.6; return @{NSForegroundColorAttributeName: self.scaleFontColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:fontSize]}; } #pragma mark - 设置界面 - (void)setupUI { // 滚动视图 _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _scrollView.showsVerticalScrollIndicator = NO; _scrollView.showsHorizontalScrollIndicator = NO; _scrollView.delegate = self; _scrollView.layer.borderWidth=0.5; _scrollView.layer.borderColor=kScaleDefaultColor.CGColor; [self addSubview:_scrollView]; // 标尺图像 _rulerImageView = [[UIImageView alloc] init]; [_scrollView addSubview:_rulerImageView]; // 指示器视图 _indicatorView = [[UIView alloc] init]; _indicatorView.backgroundColor = self.indicatorColor; [self addSubview:_indicatorView]; } #pragma mark - 属性默认值 //小刻度间距 - (CGFloat)minorScaleSpacing { if (_minorScaleSpacing <= 0) { _minorScaleSpacing = kMinorScaleDefaultSpacing; } return _minorScaleSpacing; } //主刻度长度 - (CGFloat)majorScaleLength { if (_majorScaleLength <= 0) { _majorScaleLength = kMajorScaleDefaultLength; } return _majorScaleLength; } //中间刻度长度 - (CGFloat)middleScaleLength { if (_middleScaleLength <= 0) { _middleScaleLength = kMiddleScaleDefaultLength; } return _middleScaleLength; } //小刻度长度 - (CGFloat)minorScaleLength { if (_minorScaleLength <= 0) { _minorScaleLength = kMinorScaleDefaultLength; } return _minorScaleLength; } //刻度尺背景颜色 - (UIColor *)rulerBackgroundColor { if (_rulerBackgroundColor == nil) { _rulerBackgroundColor = kRulerDefaultBackgroundColor; } return _rulerBackgroundColor; } //刻度颜色 - (UIColor *)scaleColor { if (_scaleColor == nil) { _scaleColor = kScaleDefaultColor; } return _scaleColor; } // 刻度字体颜色 - (UIColor *)scaleFontColor { if (_scaleFontColor == nil) { _scaleFontColor = kScaleDefaultFontColor; } return _scaleFontColor; } //刻度字体尺寸 - (CGFloat)scaleFontSize { if (_scaleFontSize <= 0) { _scaleFontSize = kScaleDefaultFontSize; } return _scaleFontSize; } //指示器颜色 - (UIColor *)indicatorColor { if (_indicatorView.backgroundColor == nil) { _indicatorView.backgroundColor = kIndicatorDefaultColor; } return _indicatorView.backgroundColor; } //指示器长度 - (CGFloat)indicatorLength { if (_indicatorLength <= 0) { _indicatorLength = kIndicatorDefaultLength; } return _indicatorLength; } @end
在控制器中使用:
// // SXSRulerControlVC.m // SXSInvestScaleSlider // // Created by Angela on 16/9/26. // Copyright © 2016年 iaiai. All rights reserved. //3.8M #import "SXSRulerControlVC.h" #import "SXSRulerControl.h" @interface SXSRulerControlVC ()<</span>UITextFieldDelegate> @property (nonatomic, strong) UITextField *textfield; @property (nonatomic, strong) SXSRulerControl *ruler; @end @implementation SXSRulerControlVC - (void)viewDidLoad { [super viewDidLoad]; _textfield=[[UITextField alloc]initWithFrame:CGRectMake(80, 100, 100, 40)]; _textfield.backgroundColor=[UIColor lightGrayColor]; _textfield.textAlignment=NSTextAlignmentCenter; _textfield.delegate=self; [self.view addSubview:_textfield]; _ruler = [[SXSRulerControl alloc] initWithFrame:CGRectMake(20, 0,[UIScreen mainScreen].bounds.size.width-40, 80)]; _ruler.center = self.view.center; [self.view addSubview:_ruler]; _ruler.backgroundColor = [UIColor colorWithWhite:0.93 alpha:1]; _ruler.midCount=2;//几个大格标记一个刻度 _ruler.smallCount=5;//一个大格几个小格 _ruler.minValue = 0;// 最小值 _ruler.maxValue = 3000;// 最大值 _ruler.valueStep = 400;// 两个标记刻度之间相差大小 //每个小格格大值计算为:ruler.valueStep÷(ruler.midCount*ruler.smallCount) _ruler.selectedValue = 1000;// 设置默认值 [_ruler addTarget:self action:@selector(selectedValueChanged:) forControlEvents:UIControlEventValueChanged]; // 添加监听方法 } - (void)selectedValueChanged:(SXSRulerControl *)ruler { _textfield.text = [NSString stringWithFormat:@"%.f", ruler.selectedValue]; } -(void)textFieldDidEndEditing:(UITextField *)textField{ _ruler.selectedValue=textField.text.integerValue; } -(void)textFieldDidBeginEditing:(UITextField *)textField{ _ruler.selectedValue=textField.text.integerValue; } @end