在很多时候我们都需要使用进度条来帮助我们查看进度,iOS框架自带了
progressView
来供我们使用。可是,如果我们需要圆形的⭕️进度条,那么就需要我们自定义了。嘿嘿,下面来看看怎么搞。😁
基本需求
先创建一个继承自UIView的自定义View。
里面有一个这样的方法:
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
...
}
定义文件里面加入控制进度的东西:
@property (nonatomic, assign) float progress;
- (void)changeProgress:(float)progress;
在里面实现:
CGPoint center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.width / 2);
CGFloat radius = self.bounds.size.width / 2 - 7 / 2;
//半径画出来的圆为路径中心的圆
CGFloat startA = - M_PI_2; //设置进度条起点位置
CGFloat endA = -M_PI_2 + M_PI * 2 * _progress; //设置进度条终点位置
//获取环形路径(画一个圆形,填充色透明,设置线框宽度为某值,这样就获得了一个环形)
_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.lineWidth = 7;//线的宽度
//_progressLayer.lineCap = kCALineCapButt;
//指定线的边缘类型
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];//上面说明过了用来构建圆形
_progressLayer.path = [path CGPath];
[self.layer addSublayer:_progressLayer];
将进度设为不同值,看看效果:
可以发现我们的需求已经大致达成了,我们是使用贝塞尔曲线画出了圆弧,再将进度条
layer
的路径设置为曲线路径就完成了基本需求。
进阶需求
我们还可以同通过使用一系列属性,对这个进度条的各个方面进行一些改进:
_progressLayer.lineCap = kCALineCapRound;
//指定线的边缘是圆的
圆角进度条:
虚线进度条:
_progressLayer.lineDashPattern = @[@10, @5];
//按照数组中的长度依次打断
效果:
渐变色进度条:
可以生成一个单一底色:
CALayer *gradientLayer = [CALayer layer];
gradientLayer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.width);
[gradientLayer setBackgroundColor:[UIColor redColor].CGColor];
也可以在上面添加渐变图层:
//左侧渐变色
CAGradientLayer *leftLayer = [CAGradientLayer layer];
leftLayer.frame = CGRectMake(0, 0, self.bounds.size.width / 2, self.bounds.size.width); // 分段设置渐变色
leftLayer.locations = @[@0.2, @0.8, @1];
leftLayer.colors = @[(id)[UIColor greenColor].CGColor, (id)[UIColor yellowColor].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.2, @0.8, @1];
rightLayer.colors = @[(id)[UIColor redColor].CGColor, (id)[UIColor yellowColor].CGColor];
[gradientLayer addSublayer:rightLayer];
图层效果:
创造出了一个三色渐变图层。为了让进度条颜色变成渐变,我们需要使用:
[gradientLayer setMask:_progressLayer];
//用progressLayer来截取渐变层
截取过程是怎么样呢?下面我就使用Keynote为大家演示一下。
相当于有两个图形:
截获操作相当于使用Keynote多图形操作中的交叉:
以小圆图形的形状截取大底色:
就获得了带有渐变的圆形轨道。
再将截获的圆轨加到view。
就获得了一个渐变圆环。
底轨圆环:
我们上面创建的轨道只有进度条,没有底轨条。为了美观,我们可以加入底轨,也就是相当于创建一个100%进度的底色进度条,再将我们的进度条加到轨道层上面就好啦。
_progressLayer2 = [CAShapeLayer layer];
_progressLayer2.frame = self.bounds;
_progressLayer2.fillColor = [[UIColor clearColor] CGColor];
_progressLayer2.strokeColor = [[UIColor colorWithWhite:0.9 alpha:1] CGColor];
_progressLayer2.opacity = 1;
_progressLayer2.lineWidth = 7;//线的宽度
UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:-M_PI_2 + M_PI * 2 clockwise:YES];
_progressLayer2.path = [path2 CGPath];
[self.layer addSublayer:_progressLayer2];
[_progressLayer2 addSublayer:gradientLayer];
实现效果:
动态进度条:
在
runloop
中使用计时器控制进度,就可以轻松实现进度条的动画啦
- (void)changeProgress:(float)progress {
_progress = progress;
[self setNeedsDisplay];
}
小结:
以上就是对进度条的一个使用心得。对layer的使用还在初步入门阶段,还望各位大佬指正。