Emmie Capps Emmie Capps - 23 days ago 4x
iOS Question

Button title goes behind gradient layer

I know the fact that if we add the title after assigning the gradient to the button as sublayer, button's title will be in front.

But this case is different.

I am changing gradient for normal state and touched down states of button.

Here is my code :

-(void) buttonClicked:(UIButton*)sender{

sender.backgroundColor = [UIColor clearColor];

// Finding old gradient layer to remove it
for (CALayer *layer in [sender.layer.sublayers copy]){
if ([[layer name] isEqualToString:@"gradientLayer"]) {
[layer removeFromSuperlayer];

// Applying the new gradient
UIColor *colorTwo = [UIColor colorWithRed:1.00 green:0.81 blue:0.00 alpha:0.95]; // Original
UIColor *colorThree = [[UIColor brownColor] colorWithAlphaComponent:1];
UIColor *colorFour = [[UIColor blackColor] colorWithAlphaComponent:0.9];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = sender.layer.bounds;
gradientLayer.colors = [NSArray arrayWithObjects: (id)[[UIColor whiteColor] colorWithAlphaComponent:0.5].CGColor,(id) colorTwo.CGColor,(id) colorThree.CGColor,(id) colorFour.CGColor, nil];
gradientLayer.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:1.0f], nil];
sender.layer.cornerRadius = 5;
gradientLayer.cornerRadius = sender.layer.cornerRadius;

// Adding gradient
[sender.layer addSublayer:gradientLayer];
gradientLayer.name = @"gradientLayer";

// Adding title after applying the gradient ( BUT ALSO TITLE IS GOING BEHIND THE GRADIENT )
sender.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
sender.titleLabel.numberOfLines = 2;
NSString *str = sender.titleLabel.text;
[sender setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[sender setTitle:str forState:UIControlStateNormal];

-(void) touchedDown:(UIButton*)sender{

// Finding old gradient layer to remove it
for (CALayer *layer in [sender.layer.sublayers copy]){
if ([[layer name] isEqualToString:@"gradientLayer"]) {
[layer removeFromSuperlayer];

// Applying the new gradient
CAGradientLayer *gradientLayer1 = [CAGradientLayer layer];
gradientLayer1.frame = sender.layer.bounds;
gradientLayer1.colors = [NSArray arrayWithObjects: (id)[[UIColor whiteColor] colorWithAlphaComponent:0.5].CGColor, (id)[UIColor colorWithWhite:0.4f alpha:0.2f].CGColor,(id)[UIColor colorWithWhite:0.4f alpha:0.2f].CGColor, nil];
gradientLayer1.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:1.0f], nil];
gradientLayer1.cornerRadius = sender.layer.cornerRadius;

// Adding Gradient
[sender.layer addSublayer:gradientLayer1];
gradientLayer1.name = @"gradientLayer";
sender.backgroundColor = [UIColor blackColor];
[sender setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

At first time when i launch the app, title is at front. But when i start clicking it, then the title goes behind the gradient. Kindly help me with this problem. Thanks for the time (:


The problem is this line:

[sender.layer addSublayer:gradientLayer];

That means: add the gradient layer in front of all other sublayers. That includes the layer that displays the title label.

Instead, call insertSublayer:atIndex: (or above: or below:) to position the layer among the other layers where you want it.

However, it would be even better not to mess with the button's layers directly at all. Instead of applying the gradient as a layer, draw the gradient (in code) into an image and use that image as the button's background image.

Moreover, you can configure the background image to change automatically when the user is tapping the button.