前言
最近开发一个需求,要求是一个 view 的高度逐渐变高,而 view 的背景色是一个渐变色,本来以为比较简单,做起来才发现,设置高度变化后,渐变跟着变化是有点问题的,故记录下来。
发现问题
先添加1个视图,并且添加渐变效果。
- (void)addBgView {
UIView *bgView = [UIView new];
bgView.backgroundColor = [UIColor systemPinkColor];
bgView.frame = CGRectMake(100, 100, 50, 150);
bgView.layer.cornerRadius = 25;
[self.view addSubview:bgView];
self.bgView = bgView;
CAGradientLayer *subLayer = [CAGradientLayer layer];
subLayer.colors = @[(__bridge id)[UIColor blueColor].CGColor,
(__bridge id)[UIColor yellowColor].CGColor];
subLayer.startPoint = CGPointMake(0.5, 0);
subLayer.endPoint = CGPointMake(0.5, 1);
subLayer.cornerRadius = 25;
self.gradientLayer = subLayer;
[self.bgView.layer insertSublayer:self.gradientLayer atIndex:0];
}
添加一个定时器,然后让我们的 gradientLayer 高度跟着变化。
- (void)addTimer {
static int i = 0;
__weak typeof(self) weakself = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.01 repeats:YES block:^(NSTimer * _Nonnull timer) {
i++;
weakself.gradientLayer.frame = CGRectMake(0, 0, 50, i);
weakself.animationLayer.frame = CGRectMake(250, 100, 50, i);
if (i == 150) {
[weakself.timer invalidate];
}
}];
}
展示的效果就是左边的视图。很明显右边的才是我们想要的效果。那怎么样才能实现右边的效果呢?
解决方案
解决思路:将渐变色的属性不在设置为 add 在 contentView 的子视图上,而是将渐变色的属性直接设在 contentView 本身的 layer 属性上。
- 先添加一个视图的
layerClass。
@interface AnimBgView : UIView
@end
@implementation AnimBgView
+ (Class)layerClass {
return [CAGradientLayer classForCoder];
}
- 添加
AnimBgView的CAGradientLayer。
- (void)addAnimationBgView {
self.animationBgView = [AnimBgView new];
self.animationBgView.backgroundColor = [UIColor systemPinkColor];
self.animationBgView.frame = CGRectMake(250, 100, 50, 0);
self.animationBgView.layer.cornerRadius = 25;
[self.view addSubview:self.animationBgView];
self.animationLayer = (CAGradientLayer *)self.animationBgView.layer;
self.animationLayer.colors = @[(__bridge id)[UIColor blueColor].CGColor,
(__bridge id)[UIColor yellowColor].CGColor];
self.animationLayer.startPoint = CGPointMake(0.5, 0);
self.animationLayer.endPoint = CGPointMake(0.5, 1.f);
self.animationLayer.locations = @[@(0), @(1)];
self.animationLayer.cornerRadius = 25;
}
这样就能实现效果了。
那实现的原理呢,可以参考这篇文章:www.jianshu.com/p/04f9e7a33…
实现渐变效果,和蒙版渐变效果
- 实现一个正常渐变效果。
- (void)addGradientLayer {
// 添加1个视图。
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 300, 200, 50)];
view.backgroundColor = [UIColor systemPinkColor];
[self.view addSubview:view];
// 初始化渐变
CAGradientLayer *gradientLayer = [CAGradientLayer new];
// 渐变大小
gradientLayer.frame = view.bounds;
// 渐变颜色,可以多个,对应locations。
gradientLayer.colors = @[(__bridge id)[UIColor colorWithRed:0 green:0 blue:0 alpha:0.2].CGColor, (__bridge id)[UIColor clearColor].CGColor, (__bridge id)[UIColor clearColor].CGColor, (__bridge id)[UIColor blackColor].CGColor];
// 设置每个颜色渐变范围,不写就是平分
gradientLayer.locations = @[@(0), @(0.05), @(0.95), @(1)];
// 渐变起点
gradientLayer.startPoint = CGPointMake(0, 0.5);
// 渐变重点
gradientLayer.endPoint = CGPointMake(1.0f, 0.5);
// 视图添加渐变
[view.layer addSublayer: gradientLayer];
}
- 添加蒙版渐变效果。
- (void)addMaskGradientLayer {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 450, 200, 50)];
view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:view];
CAGradientLayer *gradientLayer = [CAGradientLayer new];
gradientLayer.frame = view.bounds;
// gradientLayer.colors = @[(__bridge id)[UIColor clearColor].CGColor, (__bridge id)[UIColor blueColor].CGColor, (__bridge id)[UIColor blackColor].CGColor, (__bridge id)[UIColor clearColor].CGColor];
gradientLayer.colors = @[(__bridge id)[UIColor clearColor].CGColor, (__bridge id)[UIColor blueColor].CGColor];
// gradientLayer.locations = @[@(0), @(0.05), @(0.95), @(1)];
gradientLayer.startPoint = CGPointMake(0, 0.5);
gradientLayer.endPoint = CGPointMake(1.0f, 0.5);
view.layer.mask = gradientLayer;
}
区别:CALayer有一个属性叫做 mask,通常被称为蒙版图层。mask 的作用就是让父图层与 mask 重叠的部分区域可见, 通俗的说就是 mask 图层实心的部分将会被保留下来。
mask 作用:配合 CAGradientLayer、CAShapeLayer 使用。可以实现蒙层透明度、显示不同形状图层、图案镂空、文字变色等等功能。这个有时间再写一篇文章来实现效果。