CAGradientLayer高度变化解决

796 阅读2分钟

前言

最近开发一个需求,要求是一个 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];
        }
    }];
}

屏幕录制2022-05-15 下午10.32.22.gif

展示的效果就是左边的视图。很明显右边的才是我们想要的效果。那怎么样才能实现右边的效果呢?

解决方案

解决思路:将渐变色的属性不在设置为 add 在 contentView 的子视图上,而是将渐变色的属性直接设在 contentView 本身的 layer 属性上。

  1. 先添加一个视图的 layerClass
@interface AnimBgView : UIView

@end

@implementation AnimBgView

+ (Class)layerClass {

    return [CAGradientLayer classForCoder];

}
  1. 添加 AnimBgViewCAGradientLayer
- (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…

实现渐变效果,和蒙版渐变效果

  1. 实现一个正常渐变效果。
- (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];
}
  1. 添加蒙版渐变效果。
- (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 使用。可以实现蒙层透明度、显示不同形状图层、图案镂空、文字变色等等功能。这个有时间再写一篇文章来实现效果。