天天看點

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

在很多時候我們都需要使用進度條來幫助我們檢視進度,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];
           

将進度設為不同值,看看效果:

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:
[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

可以發現我們的需求已經大緻達成了,我們是使用貝塞爾曲線畫出了圓弧,再将進度條

layer

的路徑設定為曲線路徑就完成了基本需求。

進階需求

我們還可以同通過使用一系列屬性,對這個進度條的各個方面進行一些改進:

_progressLayer.lineCap = kCALineCapRound;
//指定線的邊緣是圓的
           

圓角進度條:

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

虛線進度條:

_progressLayer.lineDashPattern = @[@10, @5];
//按照數組中的長度依次打斷
           

效果:

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

漸變色進度條:

可以生成一個單一底色:

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];
           

圖層效果:

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

創造出了一個三色漸變圖層。為了讓進度條顔色變成漸變,我們需要使用:

[gradientLayer setMask:_progressLayer];
//用progressLayer來截取漸變層
           

截取過程是怎麼樣呢?下面我就使用Keynote為大家示範一下。

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

相當于有兩個圖形:

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

截獲操作相當于使用Keynote多圖形操作中的交叉:

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

以小圓圖形的形狀截取大底色:

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

就獲得了帶有漸變的圓形軌道。

再将截獲的圓軌加到view。

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

就獲得了一個漸變圓環。

底軌圓環:

我們上面建立的軌道隻有進度條,沒有底軌條。為了美觀,我們可以加入底軌,也就是相當于建立一個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];
           

實作效果:

[iOS開發]用CAShapeLayer實作圓形進度條基本需求進階需求小結:

動态進度條:

runloop

中使用計時器控制進度,就可以輕松實作進度條的動畫啦

- (void)changeProgress:(float)progress {
    _progress = progress;
    [self setNeedsDisplay];
}
           

小結:

以上就是對進度條的一個使用心得。對layer的使用還在初步入門階段,還望各位大佬指正。