iOS可复用控件之表盘
GitHub地址:https://github.com/runThor/HTDial
效果:
实现:
// 实际应用中,整个区域经常需要分为偏低区域、适中区域、偏高区域等不同的划分区域,要用不同的颜色标识,这里我们默认划分低、中、高三个区域,所以需要两个区域的间隔值
// HTDialView.h
#import <UIKit/UIKit.h>
@interface HTDialView : UIView
@property (nonatomic,assign)CGFloat minValue; // 表盘下限值
@property (nonatomic,assign)CGFloat maxValue; // 表盘上限值
@property (nonatomic,assign)CGFloat firstSeparationValue; // 第一个区域间隔值
@property (nonatomic,assign)CGFloat secondSeparationValue; // 第二个区域间隔值
// 设置指针指向的值
- (void)pointValue:(CGFloat)value;
@end
// HTDialView.m
#import "HTDialView.h"
@interface HTDialView ()
@property (nonatomic,strong)UIView *pointerView; // 指针
@end
@implementation HTDialView
- (void)drawRect:(CGRect)rect {
// 绘制划分区域
[self drawAreas];
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// 初始化视图
[self configViews];
}
return self;
}
// 初始化视图方法
- (void)configViews {
// 表盘轮廓
UIImageView *dialBgImgView = [[UIImageView alloc] initWithFrame:self.bounds];
dialBgImgView.image = [UIImage imageNamed:@"dial_bg"];
[self addSubview:dialBgImgView];
// 初始化指针
self.pointerView = [[UIView alloc]initWithFrame:CGRectMake(0,0,3,80)];
[self.pointerView setCenter:dialBgImgView.center];
self.pointerView.backgroundColor = [UIColor yellowColor];
self.pointerView.layer.anchorPoint = CGPointMake(0.5,0.25); // 指针旋转的支点
self.pointerView.layer.masksToBounds = YES;
// 优化渲染性能
self.pointerView.layer.shouldRasterize = YES;
self.pointerView.layer.rasterizationScale = [UIScreen mainScreen].scale;
[self addSubview:self.pointerView];
}
// 绘制划分区域及颜色
- (void)drawAreas {
if (self.minValue ==self.maxValue) {
return;
}
CGContextRef contextRef =UIGraphicsGetCurrentContext();
CGSize viewSize =self.bounds.size;
CGPoint center =CGPointMake(viewSize.width/2, viewSize.height/2);
CGFloat radius = viewSize.width/2;
// 绘制低值区域
CGFloat lowAreaAngle = (self.firstSeparationValue -self.minValue)/(self.maxValue -self.minValue) * (1.5 *M_PI);
CGContextBeginPath(contextRef);
CGContextMoveToPoint(contextRef, center.x, center.y);
CGContextAddArc(contextRef, center.x, center.y, radius,M_PI_2,M_PI_2 + lowAreaAngle,0);
CGContextSetFillColorWithColor(contextRef, [UIColor colorWithRed:0/255.0 green:102.0/255.0 blue:255.0/255.0 alpha:1.0].CGColor);
CGContextFillPath(contextRef);
// 绘制中值区域
CGFloat middleAreaAngle = (self.secondSeparationValue -self.firstSeparationValue)/(self.maxValue -self.minValue) * (1.5 *M_PI);
CGContextBeginPath(contextRef);
CGContextMoveToPoint(contextRef, center.x, center.y);
CGContextAddArc(contextRef, center.x, center.y, radius,M_PI_2 + lowAreaAngle, M_PI_2 + lowAreaAngle + middleAreaAngle,0);
CGContextSetFillColorWithColor(contextRef, [UIColor colorWithRed:13/255.0 green:142/255.0 blue:0/255.0 alpha:1.0].CGColor);
CGContextFillPath(contextRef);
// 绘制高值区域
CGContextBeginPath(contextRef);
CGContextMoveToPoint(contextRef, center.x, center.y);
CGContextAddArc(contextRef, center.x, center.y, radius,M_PI_2 + lowAreaAngle + middleAreaAngle,M_PI *2,0);
CGContextSetFillColorWithColor(contextRef, [UIColor colorWithRed:250/255.0 green:47/255.0 blue:47/255.0 alpha:1.0].CGColor);
CGContextFillPath(contextRef);
// 绘制遮罩圆,只展示环形区域
CGContextBeginPath(contextRef);
CGContextMoveToPoint(contextRef, center.x, center.y);
CGContextAddArc(contextRef, center.x, center.y, radius *0.8,0,M_PI *2,0);
CGContextSetFillColorWithColor(contextRef,self.backgroundColor.CGColor);
CGContextFillPath(contextRef);
}
// 设置指针指向的值
- (void)pointValue:(CGFloat)value {
if (self.minValue ==self.maxValue || value <self.minValue || value >self.maxValue) {
return;
}
// 指针旋转动画
[UIView animateWithDuration:1.0 animations:^{
CGFloat angle = ((value -self.minValue)/(self.maxValue -self.minValue)) * (M_PI *1.5);
if (angle >M_PI) {
// 旋转角度大于180度,需要分两步旋转,否则会逆向旋转
self.pointerView.transform =CGAffineTransformMakeRotation(M_PI);
self.pointerView.transform =CGAffineTransformMakeRotation(angle);
} else {
// 旋转角度小于等于180度,旋转一次即可
self.pointerView.transform =CGAffineTransformMakeRotation(angle);
}
}];
}
使用:
// ViewController.m
#import "ViewController.h"
#import "HTDialView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
HTDialView *dialView = [[HTDialView alloc] initWithFrame:CGRectMake(0,0, 200,200)];
dialView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
[dialView setCenter:CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2)];
dialView.minValue =0; // 下限
dialView.maxValue =100; // 上限
dialView.firstSeparationValue =30; // 第一间隔值
dialView.secondSeparationValue =60; // 第二间隔值
[dialView pointValue:50]; // 指针指向50
[self.view addSubview:dialView];
}