1. 程式人生 > >iOS UIBezierPath和CAShapeLayer畫一條多顏色的線條

iOS UIBezierPath和CAShapeLayer畫一條多顏色的線條

專案需要做一個有多個色值的進度條,笨辦法是建立多個檢視,給每個檢視設定不同顏色,當然還是畫圖更高階點。本次記錄利用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