// Created by P on 2024/11/18. #import "UIView+GradientLayer.h" #import @implementation UIView (GradientLayer) static NSString * const kGradientLayerName = @"GradientLayer"; static void *kGradientObserverKey = &kGradientObserverKey; - (void)addGradientBackgroundWithColors:(NSArray *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint cornerRadius:(CGFloat)cornerRadius { [self removeGradientBackground]; CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.name = kGradientLayerName; gradientLayer.colors = [self cgColorsFromUIColors:colors]; gradientLayer.startPoint = startPoint; gradientLayer.endPoint = endPoint; gradientLayer.cornerRadius = cornerRadius; gradientLayer.frame = self.bounds; [self.layer insertSublayer:gradientLayer atIndex:0]; [self setupLayoutObserverForGradientLayer:gradientLayer]; } - (void)updateGradientBackgroundWithColors:(NSArray *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint { CAGradientLayer *gradientLayer = [self gradientLayer]; if (gradientLayer) { gradientLayer.colors = [self cgColorsFromUIColors:colors]; gradientLayer.startPoint = startPoint; gradientLayer.endPoint = endPoint; } } - (void)removeGradientBackground { CAGradientLayer *gradientLayer = [self gradientLayer]; if (gradientLayer) { [gradientLayer removeFromSuperlayer]; } if ([self hasAddedObserver]) { [self removeObserver:self forKeyPath:@"bounds"]; [self setHasAddedObserver:NO]; } } - (CAGradientLayer *)gradientLayer { for (CALayer *layer in self.layer.sublayers) { if ([layer.name isEqualToString:kGradientLayerName] && [layer isKindOfClass:[CAGradientLayer class]]) { return (CAGradientLayer *)layer; } } return nil; } - (void)setupLayoutObserverForGradientLayer:(CAGradientLayer *)gradientLayer { if (![self hasAddedObserver]) { [self addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew context:(__bridge void *)gradientLayer]; [self setHasAddedObserver:YES]; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"bounds"]) { CAGradientLayer *gradientLayer = (__bridge CAGradientLayer *)context; gradientLayer.frame = self.bounds; } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } - (NSArray *)cgColorsFromUIColors:(NSArray *)colors { NSMutableArray *cgColors = [NSMutableArray array]; for (UIColor *color in colors) { [cgColors addObject:(id)color.CGColor]; } return [cgColors copy]; } - (BOOL)hasAddedObserver { return [objc_getAssociatedObject(self, kGradientObserverKey) boolValue]; } - (void)setHasAddedObserver:(BOOL)added { objc_setAssociatedObject(self, kGradientObserverKey, @(added), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end