iOS可复用控件之表盘

GitHub地址:https://github.com/runThor/HTDial

效果:

iOS可复用控件之表盘


实现:

// 实际应用中,整个区域经常需要分为偏低区域、适中区域、偏高区域等不同的划分区域,要用不同的颜色标识,这里我们默认划分低、中、高三个区域,所以需要两个区域的间隔值

//  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 allocinitWithFrame: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];

}