iOS UIBezierPath和CAShapeLayer畫一條多顏色的線條
阿新 • • 發佈:2019-02-13
專案需要做一個有多個色值的進度條,笨辦法是建立多個檢視,給每個檢視設定不同顏色,當然還是畫圖更高階點。本次記錄利用UIBezierPath和CAShapeLayer來畫一條多顏色的線條。
首先我們要先知道整個線條的所有色值,和當前的結果,也就是偏高然後建立顏色線條類,呼叫:
NSString *resutStr = @"偏高"; NSArray *colorArr = @[@{@"title":@"極低", @"color":[UIColor redColor]}, @{@"title":@"較低", @"color":[UIColor orangeColor]}, @{@"title":@"偏低", @"color":[UIColor yellowColor]}, @{@"title":@"正常", @"color":[UIColor greenColor]}, @{@"title":@"偏高", @"color":[UIColor cyanColor]}, @{@"title":@"較高", @"color":[UIColor blueColor]}, @{@"title":@"極高", @"color":[UIColor purpleColor]}]; ColorLineView *lineView = [[ColorLineView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 44) levelArr:colorArr currentLevel:resutStr]; [self.view addSubview:lineView];
ColorLineView.m:
@interface ColorLineView () @property (nonatomic,strong) NSArray *levelArr; @property (nonatomic,copy) NSString *remark; @end @implementation ColorLineView -(instancetype)initWithFrame:(CGRect)frame levelArr:(NSArray *)levelArr currentLevel:(NSString *)remark { if (self = [super initWithFrame:frame]) { _levelArr = levelArr; _remark = remark; [self setupUI]; } return self; } -(void)setupUI { //計算當前等級下標 __block NSInteger index = 0; __block NSInteger normalIndex = 0; [self.levelArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj[@"title"] isEqualToString:@"正常"]) { normalIndex = idx; } if ([obj[@"title"] isEqualToString:_remark]) { index = idx; } }]; //等級名 CGFloat lineW = self.bounds.size.width-40; UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 80, 14)]; titleLabel.center = CGPointMake(20 + lineW/self.levelArr.count*index + lineW/self.levelArr.count/2, 7); [self addSubview:titleLabel]; titleLabel.textAlignment = NSTextAlignmentCenter; titleLabel.textColor = self.levelArr[index][@"color"]; titleLabel.font = [UIFont systemFontOfSize:10]; titleLabel.text = [_remark isEqualToString:@"正常"] ? @" " : _remark; //三角標 UIView *triangleView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(titleLabel.frame)-5, CGRectGetMaxY(titleLabel.frame), 10, 6)]; [self addSubview:triangleView]; [self drawTriangle:triangleView color:self.levelArr[index][@"color"]]; //等級條 UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(20, CGRectGetMaxY(triangleView.frame), lineW, 10)]; lineView.layer.cornerRadius = 5; lineView.layer.masksToBounds = YES; [self addSubview:lineView]; [self setupLineView:lineView colors:self.levelArr]; //正常 UILabel *normalLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(lineView.frame), 30, 14)]; normalLabel.center = CGPointMake(20 + lineW/self.levelArr.count*normalIndex + lineW/self.levelArr.count/2, CGRectGetMaxY(lineView.frame)+7); [self addSubview:normalLabel]; normalLabel.textColor = self.levelArr[normalIndex][@"color"]; normalLabel.textAlignment = NSTextAlignmentCenter; normalLabel.font = [UIFont systemFontOfSize:10]; normalLabel.text = @"正常"; } //畫三角標 -(void)drawTriangle:(UIView *)triangleView color:(UIColor *)color { UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(0, 0)]; [path addLineToPoint:CGPointMake(10, 0)]; [path addLineToPoint:CGPointMake(5, 6)]; [path closePath]; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = path.CGPath; shapeLayer.fillColor = color.CGColor; [triangleView.layer addSublayer:shapeLayer]; } //畫等級條顏色 -(void)setupLineView:(UIView *)lineView colors:(NSArray *)colorArr { UIBezierPath *linePath = [UIBezierPath bezierPath]; [linePath moveToPoint:CGPointMake(0, lineView.bounds.size.height/2)]; [linePath addLineToPoint:CGPointMake(lineView.bounds.size.width, lineView.bounds.size.height/2)]; __block float a = 0; [colorArr enumerateObjectsUsingBlock:^(NSDictionary * obj, NSUInteger idx, BOOL * _Nonnull stop) { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; //每次動畫的持續時間 animation.duration = 0.25; //動畫起始位置 animation.fromValue = @(0); //動畫結束位置 animation.toValue = @(1); CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = linePath.CGPath; shapeLayer.lineWidth = lineView.bounds.size.height; shapeLayer.fillColor = nil; shapeLayer.strokeColor = [obj[@"color"] CGColor]; //strokeStart defaults to zero and strokeEnd to one. shapeLayer.strokeStart = a; //分成了多少段,每次加多少分之一 shapeLayer.strokeEnd = a + 1.0/colorArr.count; //新增動畫 [shapeLayer addAnimation:animation forKey:@"strokeEndAnimation"]; [lineView.layer addSublayer:shapeLayer]; a = shapeLayer.strokeEnd; }]; } @end