iOS一分钟学会环形进度条

作者: 夜千寻墨 | 来源:发表于2016-02-27 18:50 被阅读20506次

    有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现。
    先看一下这篇博客,博客地址:http://www.brighttj.com/ios/ios-implement-loop-progress.html
    这篇博客写的不错,不过看上去还是略微复杂了,我自己根据自己的思路整理了一下,当然目的是为了更加简洁易懂。

    一:先制作一个不带颜色渐变的进度条

    自定义一个cycleView,在.m 中实现drawRect方法

    - (void)drawRect:(CGRect)rect {
        
        CGContextRef ctx = UIGraphicsGetCurrentContext();//获取上下文
        
        CGPoint center = CGPointMake(100, 100);  //设置圆心位置
        CGFloat radius = 90;  //设置半径
        CGFloat startA = - M_PI_2;  //圆起点位置
        CGFloat endA = -M_PI_2 + M_PI * 2 * _progress;  //圆终点位置
        
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
        
        CGContextSetLineWidth(ctx, 10); //设置线条宽度
        [[UIColor blueColor] setStroke]; //设置描边颜色
        
        CGContextAddPath(ctx, path.CGPath); //把路径添加到上下文
        
        CGContextStrokePath(ctx);  //渲染
    
    }
    
    

    <br />

    因为drawRect方法只是在视图刚刚出现的时候执行一次,所以我们需要使用

    [self setNeedsDisplay];<br />

    这个方法来进行重新绘制,
    在控制器里面加一个slider,滑动slider来控制进度变化

    - (void)drawProgress:(CGFloat )progress
    {
        _progress = progress;
        [self setNeedsDisplay];
    }
    

    看一下效果

    0.png

    如果进度条不需要加渐变色,那么这儿几行代码就完成了。

    下面来实现一下带有渐变色的进度条,原理很简单,刚刚画的是一条默认是黑色的线条,我们把黑色替换成一条渐变色的线条就可以了。
    环形渐变色线条的制作:

    第一步

    使用CAShapeLayer绘制出渐变层,应为它只能指定两个点之间进行渐变,所以这里需要两个CAShapeLayer,左边一个和右边一个,看一下效果图

    3.jpg

    代码实现

    
    //生成渐变色
        CALayer *gradientLayer = [CALayer layer];
        
        //左侧渐变色
        CAGradientLayer *leftLayer = [CAGradientLayer layer];
        leftLayer.frame = CGRectMake(0, 0, self.bounds.size.width / 2, self.bounds.size.height);    // 分段设置渐变色
        leftLayer.locations = @[@0.3, @0.9, @1];
        leftLayer.colors = @[(id)[UIColor yellowColor].CGColor, (id)[UIColor greenColor].CGColor];
        [gradientLayer addSublayer:leftLayer];
        
        //右侧渐变色
        CAGradientLayer *rightLayer = [CAGradientLayer layer];
        rightLayer.frame = CGRectMake(self.bounds.size.width / 2, 0, self.bounds.size.width / 2, self.bounds.size.height);
        rightLayer.locations = @[@0.3, @0.9, @1];
        rightLayer.colors = @[(id)[UIColor yellowColor].CGColor, (id)[UIColor redColor].CGColor];
        [gradientLayer addSublayer:rightLayer];
        
    

    这个渐变层只是一个中间变量,是不能显示出来的,我这里只是演示一下,现在我们已经拿到了渐变层gradientLayer。

    第二步

    我们需要制作一个环形路径
    先看一下效果:


    2.jpg

    代码实现:

    CGPoint center = CGPointMake(100, 100);
        CGFloat radius = 90;
        CGFloat startA = - M_PI_2;  //设置进度条起点位置
        CGFloat endA = -M_PI_2 + M_PI * 2 * _progress;  //设置进度条终点位置
        
        //获取环形路径(画一个圆形,填充色透明,设置线框宽度为10,这样就获得了一个环形)
        _progressLayer = [CAShapeLayer layer];//创建一个track shape layer
        _progressLayer.frame = self.bounds;
        _progressLayer.fillColor = [[UIColor clearColor] CGColor];  //填充色为无色
        _progressLayer.strokeColor = [[UIColor redColor] CGColor]; //指定path的渲染颜色,这里可以设置任意不透明颜色
        _progressLayer.opacity = 1; //背景颜色的透明度
        _progressLayer.lineCap = kCALineCapRound;//指定线的边缘是圆的
        _progressLayer.lineWidth = 10;//线的宽度
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];//上面说明过了用来构建圆形
        _progressLayer.path =[path CGPath]; //把path传递給layer,然后layer会处理相应的渲染,整个逻辑和CoreGraph是一致的。
        [self.layer addSublayer:_progressLayer];
    
    

    第三步,也是最后一步了

    用我们在第二步生成的环形路径去截取第一步生成的渐变层

    [gradientLayer setMask:_progressLayer]; //用progressLayer来截取渐变层
    self.layer addSublayer:gradientLayer];
    

    截取的layer层就是我们最后需要的,看一看我们最后截取后得到的

    4.jpg

    到这里,我们已经完成了99%了,最后一步,根据自己的需要让它显示多少的比例就完成了。比例的控制在第二部的progress属性,比例在0-1之间,看一看最后的效果。

    1.jpg

    demo下载地址

    更多原创文章可以看 我的博客

    相关文章

      网友评论

      • SoaringHeart:红色背景不显示
      • 夢若繁星:想问下 label没有显示是什么问题啊?
      • Harper_X:有矩形的吗?
      • 甘邦:Label没有显示出来啊,楼主~~
      • d7e8b53e0f42:你确定在drawRect里面addSublayer是个明智的选择?划几次之后看看self.layer.sublayers.count的值,会有惊喜
        遗忘国崎:我收回我的话,看了楼主传在git上面的代码,真的是,看的人不舒服
        遗忘国崎:没必要这么阴阳怪气的,楼主只是叫你实现环形进度条的,你看实现进度条的部分不就行了
      • 无神:环形路径的渐变色是由深蓝到浅蓝,这种的如何设置,求教?@夜千寻墨:smiley:
        夜千寻墨:@林_柏显 没有,类似吧,或者有很好的方法
        无神:@林_柏显 ;没有啊
        林_柏显:你好,7种颜色渐变弄过吗
      • Samson_Xu:想问下,怎么根据传入的值设置自动绘制到指定位置,而不是手动滑动绘制
        夜千寻墨:@Samson_Xu 不是提供一个方法了麽
      • 开小飞:这个圆环绘制的时候可以加动画效果么?如果不是从0开始的话,会突然出现,这样效果不是很好啊
      • playcoolC:drawRect的性能不好
        KenZhangCn:@cc_Jumper 耗CPU省GPU
        cc_Jumper:@playcoolC 为什么,不是鼓励用这个画图么 :hushed:
      • David_Do:有错别字,CAGradientLayer是渐变层,你写成了CAShapelayer
      • ryugaku:收藏了
      • 云无心:前排提问, 请问为什么- (void)drawProgress:(CGFloat )progress这个方法中设置_progressLayer.opacity = 0; 而在drawRect中却 _progressLayer.opacity = 1;呢, 而且不加前者会异常卡顿而且不会清空原来的,,,,写着问题我知道了,,就是会清空原来的,但是为什么不写会卡顿呢
        3a0dd2a4c4c4:感觉你这样一直添加layer是不好的 ,应该要removefromsuperlayer
        3a0dd2a4c4c4:不太清楚你这个将透明度设为0是啥意思 不可以直接用[self removefromsuperlayer]方法么
        夜千寻墨:@云无心 那不是卡顿,这个相当于画画,每次画个新的就要把原来的清空了。不清空的话之前的图层一直存在

      本文标题:iOS一分钟学会环形进度条

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