愈來愈多的應用,在等待網絡時使用閃爍的效果,那麼這種效果,如何實現?且聽我娓娓道來,相關代碼已經放在githubgit
獲取每一個控件,而且求出控件的path(也就是控件最外邊的那些線),本來的控件遮罩只是矩形,爲了美觀,我建議每一個控件path添加圓角程序員
// 獲取每一個子控件的path,用於後面的加遮蓋 mask layer
// 添加圓角
UIBezierPath *defaultCoverblePath = [UIBezierPath bezierPathWithRoundedRect:subview.bounds cornerRadius:subview.frame.size.height/2.0/*subview.layer.cornerRadius*/];
if ([subview isMemberOfClass:[UILabel class]] || [subview isMemberOfClass:[UITextView class]]) {
defaultCoverblePath = [UIBezierPath bezierPathWithRoundedRect:subview.bounds cornerRadius:4];
}
UIBezierPath *relativePath = defaultCoverblePath;
// 計算subview相對super的view的frame
CGPoint offsetPoint = [subview convertRect:subview.bounds toView:view].origin;
[subview layoutIfNeeded];
[relativePath applyTransform:CGAffineTransformMakeTranslation(offsetPoint.x, offsetPoint.y)];
UIBezierPath *totalCoverablePath = [[UIBezierPath alloc] init];
[totalCoverablePath appendPath:relativePath];
複製代碼
一、 添加覆蓋控件的覆蓋層github
二、 添加漸變色圖層到擋住控件的覆蓋層網絡
三、爲漸變色圖層設置mask,從而顯示mask面積下面的漸變色圖層(原理看下方)app
// 添加擋住全部控件的覆蓋層(擋住整superview,包括 superview 的子控件)
self.viewCover.frame = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
[view addSubview:self.viewCover];
// gradientLayer CAGradientLayer是CALayer的一個子類,用來生成漸變色圖層
CAGradientLayer *colorLayer = [CAGradientLayer layer];
colorLayer.frame = (CGRect)self.view.bounds;
colorLayer.startPoint = CGPointMake(-1.4, 0);
colorLayer.endPoint = CGPointMake(1.4, 0);
// 顏色分割線
colorLayer.colors = @[(__bridge id)[UIColor colorWithRed:0 green:0 blue:0 alpha:0.03].CGColor,(__bridge id)[UIColor colorWithRed:0 green:0 blue:0 alpha:0.1].CGColor,(__bridge id)[UIColor colorWithRed:1 green:1 blue:1 alpha:0.02].CGColor, (__bridge id)[UIColor colorWithRed:0 green:0 blue:0 alpha:0.06].CGColor, (__bridge id)[UIColor colorWithRed:0 green:0 blue:0 alpha:0.04].CGColor];
colorLayer.locations = @[
[NSNumber numberWithDouble:colorLayer.startPoint.x],
[NSNumber numberWithDouble:colorLayer.startPoint.x],
@0,
[NSNumber numberWithDouble:0.2],
[NSNumber numberWithDouble:1.2]];
[self.viewCover.layer addSublayer:colorLayer];
// superview添加mask(能顯示的遮罩)
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = totalCoverablePath.CGPath;
maskLayer.fillColor = [UIColor whiteColor].CGColor;
colorLayer.mask = maskLayer;
複製代碼
原理:動畫
遮罩層必須至少有兩個圖層,上面的一個圖層爲「遮罩層」,下面的稱「被遮罩層」;這兩個圖層中只有相重疊的地方纔會被顯示。也就是說在遮罩層中有對象的地方就是「透明」的,能夠看到被遮罩層中的對象,而沒有對象的地方就是不透明的,被遮罩層中相應位置的對象是看不見的。 它的原理是:上面一層是遮罩層,下面一層是被遮罩層。遮罩層上的圖,本身是不顯示的。它只起到一個透光的做用。假定遮罩層上是一個正圓,那麼光線就會透過這個圓形,射到下面的被遮罩層上,只會顯示一個圓形的圖形。若是遮罩層上什麼都沒有,那麼光線就沒法透到下面來,那麼下面的被遮罩層什麼也顯示不出來。ui
上述代碼,得出以下效果: spa
上述效果,其實不少app就單純這樣使用了,可是咱們爲了更美化,決定爲其增長動態效果// 動畫 animate
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"locations"];
animation.fromValue = colorLayer.locations;
animation.toValue = @[
@0,
@1,
@1,
@1.2,
@1.2];
animation.duration = 0.7;
animation.repeatCount = HUGE;
[animation setRemovedOnCompletion:NO];
// 爲漸變層增長添加動畫
[colorLayer addAnimation:animation forKey:@"locations-layer"];
複製代碼
// 移除動態效果以及圖層
[self.colorLayer removeAllAnimations];
[self.colorLayer removeFromSuperlayer];
[self.maskLayer removeFromSuperlayer];
// 移除控件的覆蓋層
[self.viewCover removeFromSuperview];
複製代碼
就這樣,完成了一個主流APP的Loding圖,我針對此代碼還進行了特殊封裝,代碼已經放在github code
歡迎關注技術公衆號 「程序員大咖秀」orm