美文网首页
iOS圆环,环形渐变进度条的封装

iOS圆环,环形渐变进度条的封装

作者: Alex1989 | 来源:发表于2021-01-04 10:47 被阅读0次

    先来看效果(demo在下方):

    Kapture 2021-01-04 at 11.17.13.gif

    实现思路:

    • 配置圆环进度参数,因为我们需要控件的复用,所以会把一些关键API设置为动态可调整的
      圆环参数配置的API
    @interface AGSCircleViewConfig : NSObject
    
    //环形宽度
    @property (nonatomic, assign) CGFloat circleLineWidth;
    //环形颜色
    @property (nonatomic, strong) UIColor *lineColor;
    // 是否顺时针:yes顺 No逆
    @property (nonatomic, assign) BOOL isClockwise;
    // 起始坐标
    @property (nonatomic, assign) CGPoint startPoint;
    // 结束坐标
    @property (nonatomic, assign) CGPoint endPoint;
    
    
    //这俩数组必须相等
    //渐变色的颜色数组
    @property (nonatomic, strong) NSArray *colorArr;
    // 渐变色颜色的位置数组从左到右排列
    @property (nonatomic, strong) NSArray *colorSize;
    
    
    @end
    
    • 绘制背景圆实现思路
      使用UIBezierPath绘制圆环路径
      把路径设置到CAShapeLayer上,画出背景圆环
    - (void)drawBackCircleView {
        
        //1.UIBezierPath创建一个圆环路径
        //圆心
        CGPoint arcCenter = CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0);
        //半径 , circleLineWidth = 圆环线条宽度
        CGFloat radius = (self.frame.size.width - _configure.circleLineWidth)/2.0;
        //开始弧度:-M_PI_2,竖直向上; 结束弧度:-M_PI_2 + M_PI*2,一圈 clockwise:YES逆时针 NO顺时针
        //clockwise = NO时,若结束弧度 = -M_PI_2 + M_PI*2, 则圆环消失归零
        UIBezierPath *circle = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:radius  startAngle:-M_PI_2 endAngle:-M_PI_2 + M_PI*2 clockwise:YES];
        
        //2.创建一个ShapeLayer
        CAShapeLayer *bgLayer = [CAShapeLayer layer];
        bgLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.width);
        bgLayer.fillColor = [UIColor clearColor].CGColor;//圆环路径填充颜色
        bgLayer.lineWidth = _configure.circleLineWidth;//圆环宽度
        bgLayer.strokeColor = _configure.lineColor.CGColor;//路径颜色
        bgLayer.strokeStart = 0.f;//路径开始位置
        bgLayer.strokeEnd = 1.f;//路径结束位置
        bgLayer.path = circle.CGPath;
        
        //3.把路径设置到layer上,画出背景圆环
        [self.layer addSublayer:bgLayer];
    }
    
    • 绘制进度圆环,实现思路:
      1.绘制圆弧路径:使用CGContextRef
      2.创建渐变色:使用CGColorSpaceRef
      3.画出圆环路径并裁剪:使用CGContextReplacePathWithStrokedPathheCGContextClip
      4.使用渐变色填充:使用CGContextDrawLinearGradient
      核心代码:
    - (void)drawRect:(CGRect)rect {
        
        // 1. 还是添加一个圆弧路径
        //获取图形上下文
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        //设置线的宽度
        CGContextSetLineWidth(ctx, _configure.circleLineWidth);
        //设置圆环线条的两个端点做圆滑处理
        CGContextSetLineCap(ctx, kCGLineCapRound);
        //设置画笔颜色
        CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
        //设置圆心
        CGFloat originX = rect.size.width / 2;
        CGFloat originY = rect.size.height / 2;
        //计算半径
        CGFloat radius = MIN(originX, originY) - _configure.circleLineWidth/2.0;
        //建立一个最小初始弧度制,避免进度progress为0或1时圆环消失
        CGFloat minAngle = M_PI/90 - self.progress * M_PI/80;
        //逆时针画一个圆弧
        if (self.configure.isClockwise) {
    
            CGContextAddArc(ctx, rect.size.width / 2, rect.size.height / 2, radius, -M_PI_2, -M_PI_2 + minAngle + (2 * M_PI)*self.progress, NO);
        }else{
            
            CGContextAddArc(ctx, rect.size.width / 2, rect.size.height / 2, radius, -M_PI_2, -M_PI_2 - minAngle + (2 * M_PI)*(1-self.progress), YES);
        }
        
        //2. 创建一个渐变色
        CGFloat locations[_configure.colorSize.count];
        for (NSInteger index = 0; index < _configure.colorSize.count; index++) {
            locations[index] = [_configure.colorSize[index] floatValue];
        }
        
        //创建RGB色彩空间,创建这个以后,context里面用的颜色都是用RGB表示
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,(__bridge CFArrayRef _Nonnull)_configure.colorArr, _configure.colorSize.count==0?NULL:locations);
    
        //释放色彩空间
        CGColorSpaceRelease(colorSpace);
        colorSpace = NULL;
        
        //3.画出圆环路径
        CGContextReplacePathWithStrokedPath(ctx);
        //剪裁路径
        CGContextClip(ctx);
        
        //4.用渐变色填充,修改填充色的方向,_startPoint和_endPoint两个点的连线,就是颜色的分布方向
        CGContextDrawLinearGradient(ctx, gradient, _configure.startPoint, _configure.endPoint, 1);
        
        //释放渐变色
        CGGradientRelease(gradient);
        
    }
    
    • 由于我们圆环进度的实现是在drawRect方法上,更新进度,绘制要调用setNeedsDisplay
    - (void)setProgress:(float)progress {
        _progress = progress;
        _circleView.progress = progress;
        
        [_circleView setNeedsDisplay];
    }
    

    完整Demo奉上:

    https://github.com/alexgaosun/AGSCircleProgressDemo

    相关文章

      网友评论

          本文标题:iOS圆环,环形渐变进度条的封装

          本文链接:https://www.haomeiwen.com/subject/rpwmoktx.html