UIView CAGradient with rounded corners?

6.8k views Asked by At

I have an UIView with rounded corners and drop shadow, implemented and working. But the UIView has a boring background color, white. So I want to put a gradient layer as the background. Below the labels, buttons and most important, make it so the rounded corners still appears.

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = subHudView.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], (id)[[UIColor whiteColor] CGColor], nil];
[subHudView.layer addSublayer:gradient];
subHudView.layer.cornerRadius = 8;
subHudView.layer.masksToBounds = NO;
subHudView.layer.shadowOffset = CGSizeMake(-5, 5);
subHudView.layer.shadowRadius = 8;
subHudView.layer.shadowOpacity = 0.75;

This is my code as I tried to implement it, but the gradient layer is on top of everything in the view know. How can I make the gradient go under all the controls and labels? Every responding help will be appreciated.

5

There are 5 answers

4
gcamp On BEST ANSWER

When you addSublayer: it add the layer at the top of all the sublayers.

You should probably use something like that instead :

[subHudView.layer insertSublayer:gradient atIndex:0];

That way, the CAGradientLayer will be below everything else.

0
ytp92 On

in Swift:

let gradientLayer = CAGradientLayer()
gradientLayer.cornerRadius = 20.0
7
matt On

A layer added to your view (addSublayer) is drawn in front of your view's own layer, which is where all your view's drawing takes place. What you want is to draw the gradient into your view's own layer. To do so, implement +layerClass in your view, specifying that you want your view's layer to be a gradient view.

So, for example (in the view's own code):

+(Class)layerClass {
    return [CAGradientLayer class];
}

-(void)awakeFromNib {
    [super awakeFromNib];
    CAGradientLayer* layer = (CAGradientLayer*)self.layer;
    layer.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], (id)[[UIColor whiteColor] CGColor], nil];
    layer.cornerRadius = 8;
    layer.masksToBounds = NO;
    layer.shadowOffset = CGSizeMake(-5, 5);
    layer.shadowRadius = 8;
    layer.shadowOpacity = 0.75;
}

If you then implement drawRect:, however, you'll of course wipe out your gradient and your rounded corners. There are ways around that...

0
eric.mitchell On

As well as the insertSublayer:atIndex: that gcamp suggested, you can also use insertSublayer:above: and insertSublayer:below: to place your layer in specific places.

[self.view.layer insertSublayer:gradient below:someUIObject];
0
tarmes On

Rather than create a new layer, override your view's layer method:

+ (Class)layerClass
{
    return [CAGradientLayer class];
}

This will ensure that your view create a CAGradientLayer, rather than a basic CALayer, as the base layer.

Then, during init get hold of the layer:

CAGradientLayer *gradLayer = self.layer;
gradLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], (id)[[UIColor whiteColor] CGColor], nil];

and assign your gradients to it.

Nice and clean...