CAGradientLayer in UITableViewCell

665 Views Asked by At

I have a UITableViewCell that has an UIView (gradientView) where I want to apply the gradient. This cell has AutoLayout, and so I want to update the gradient frame when the gradientView frame changes.

I have tried the following, but none of them worked:

-(void)layoutSubviews{
    [super layoutSubviews];
     self.gradient.frame = self.gradientView.bounds;
}

-(void)updateConstraints{
    [super updateConstraints];
    self.gradient.frame = self.gradientView.bounds;
}

-(void)updateConstraintsIfNeeded{
    [super updateConstraintsIfNeeded];
    self.gradient.frame = self.gradientView.bounds;
}

also I can't use this inside the cell:

- (void)viewDidLayoutSubviews{}
2

There are 2 best solutions below

2
On BEST ANSWER

I'd suggest create a new UIView subclass whose backing layer (layerClass) is a CAGradientLayer. Apply the colors as needed. Whenever the view's bounds change, iOS will internally resize the layer too.

If you want to make it even simpler, just grab OBGradientView from here and use it in your project. https://github.com/ole/OBGradientView

3
On

Personally I always use KVO for changing layers frame. Put this line after cell subviews has been loaded (-(void)awakeFromNib if you're using IB/storyboards). It's important that this line will be called only once in cells lifetime!

[self.gradientView.layer addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew context:nil];

then just implement this method:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if(object==self.gradientView.layer && self.gradient.superlayer!=nil){
        CGRect newFrame = [change[NSKeyValueChangeNewKey] CGRectValue];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.gradient.frame = newFrame;
        });
    }
}

I put frame update in dispatch_async block since without it layer was not updated.

And don't forget to remove observer eg. in dealloc:

-(void)dealloc{
    [self.gradientView.layer removeObserver:self forKeyPath:@"bounds"];
}