iOS仿刻度尺demo

效果:
[img]http://dl2.iteye.com/upload/attachment/0122/7116/d3b3e3b2-c870-3e43-9957-872957254565.png[/img]
.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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值