標籤:
之前有人在找漸層進度條的效果,閑來無事就順手寫了一個,然後畫了視圖層級,方便講解。
環境資訊:
Mac OS X 10.10.3
Xcode 6.3.1
iOS 8.3
:
源碼:
https://github.com/saitjr/LoopProgressDemo.git
本文
一、視圖層級
首先需要搞定的就是視圖層級關係。可以看到,
1. 背景是有透明度的藍色(blueView)
2. 需要一個從綠->黃->紅的漸層色,那個這裡我採用的是Layer(colorLayer)
3. blueView和colorLayer他們的表現狀態都是環形的,所以還需要環形的遮罩
4. 藍色的環並沒有變,而漸層色的環卻在時刻變化,所以需要兩個遮罩,一個給藍色(blueMaskLayer),一個給漸層色(colorMaskLayer)
從上面的分析可以看出,現在需要幾個變數以及他們的關係如下:
[viewController.view addSubView:blueView];[blueView.layer addSubLayer:colorLayer];colorLayer.mask = colorMaskLayer;blueView.layer.mask = blueMaskLayer;
視圖層級圖如下:
視圖層級圖
二、根據視圖層級來實現
搞清楚了層級,接著就應該逐個實現了。
1. 有透明度的藍色視圖blueView
ViewController.m
BlueView *blueView = [[BlueView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];blueView.center = self.view.center;blueView.backgroundColor = [UIColor blueColor]; // 我這裡沒有給透明度[self.view addSubView:blueView];
2. 漸層圖層colorLayer
因為系統沒有提供根據路徑漸層的實現方法,所以只能採用曲線救國的方式來畫。那麼我所使用的方法是:在左邊畫一個從下往上為綠->黃的漸層Layer(leftLayer),然後右邊畫一個從下往上為紅->黃的漸層Layer(rightLayer)。
如下:
漸層色
但是這種方式效果不是很好,因為黃綠色和橘紅色的分界太明顯,所以最好設定一個漸層的範圍。
如下:
設定漸層範圍的漸層色
實現代碼:
BlueView.m
- (void)setupColorLayer { self.colorLayer = [CAShapeLayer layer]; self.colorLayer.frame = self.bounds; [self.layer addSublayer:self.colorLayer]; 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]; [self.colorLayer 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]; [self.colorLayer addSublayer:rightLayer];}
3. 漸層圖層的環形遮罩colorMaskLayer
因為漸層圖層環形遮罩和藍色視圖的環形遮罩樣式都是一樣的,所以可以將環形遮罩的建立代碼封裝出來:
BlueView.m
- (CAShapeLayer *)generateMaskLayer { CAShapeLayer *layer = [CAShapeLayer layer]; layer.frame = self.bounds; // 建立一個圓心為父視圖中點的圓,半徑為父視圖寬的2/5,起始角度是從-240°到60° UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2) radius:self.bounds.size.width / 2.5 startAngle:-3 / 4 * M_PI endAngle:1 / 3 * M_PI clockwise:YES]; layer.lineWidth = 20; layer.path = path.CGPath; layer.fillColor = [UIColor clearColor].CGColor; // 填充色為透明(不設定為黑色) layer.strokeColor = [UIColor blackColor].CGColor; // 隨便設定一個邊框顏色 layer.lineCap = kCALineCapRound; // 設定線為圓角 return layer;}
設定漸層色環形遮罩層
BlueView.m
- (void)setupColorMaskLayer { CAShapeLayer *layer = [self generateMaskLayer]; layer.lineWidth = 20.5; // 漸層遮罩線寬較大,防止藍色遮罩有邊露出來 self.colorLayer.mask = layer; self.colorMaskLayer = [CAShapeLayer layer]; self.colorMaskLayer = layer;}
4. blueView的環形遮罩blueMaskLayer
BlueView.m
- (void)setupBlueMaskLayer { CAShapeLayer *layer = [self generateMaskLayer]; self.layer.mask = layer; self.blueMaskLayer = layer;}
5. 設定百分比
設定漸層色所佔的百分比,其實就是改變colorMaskLayer的範圍,系統提供了一個方法可以直接根據百分比來修改。
self.colorMaskLayer.strokeEnd = 0.5;
到此,整個效果就已經完成了,接下來說一下回彈動畫。
三、設定回彈動畫
我所使用的是pop庫中的POPSpringAnimation,這個效果比較Q彈,加在進度條上剛好。要加動畫,只需要把上面的修改strokeEnd的代碼換成一下方法就可以了:
- (void)animationWithStrokeEnd:(CGFloat)strokeEnd { POPSpringAnimation *strokeAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd]; strokeAnimation.toValue = @(strokeEnd); strokeAnimation.springBounciness = 12.f; strokeAnimation.removedOnCompletion = NO; [self.colorMaskLayer pop_addAnimation:strokeAnimation forKey:@"layerStrokeAnimation"];}
【iOS】環形漸層進度條實現