Button title goes behind gradient layer - ios

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.

Related

Unable to set gradient on uiview using layer

I have set color for uicontrollerview from stroyboard but I want gradient in the background color. So coded the required layer in viewdidappear still its not appearing.
-(void)viewDidAppear:(BOOL)animated{
[self setBackGradient];
}
-(void)setBackGradient{
CAGradientLayer *grad = [CAGradientLayer layer];
grad.frame = self.view.bounds;
UIColor *topColor=[UIColor colorWithRed:0.91 green:0.94 blue:0.99 alpha:1.0];
UIColor *bottomColor=[UIColor colorWithRed:0.67 green:0.80 blue:0.93 alpha:1.0];
NSArray *colorsArr=[[NSArray alloc]initWithObjects:topColor,bottomColor, nil];
grad.colors=colorsArr;
grad.masksToBounds=YES;
[self.view.layer insertSublayer:grad atIndex:0];
}
The colors for a layer need to be CGColors. Try the following:
-(void)setBackGradient{
CAGradientLayer *grad = [CAGradientLayer layer];
grad.frame = self.view.bounds;
NSArray *colorsArr=#[(id)[UIColor colorWithRed:0.91 green:0.94 blue:0.99 alpha:1.0].CGColor, (id)[UIColor colorWithRed:0.67 green:0.80 blue:0.93 alpha:1.0].CGColor];
grad.colors=colorsArr;
grad.masksToBounds=YES;
[self.view.layer insertSublayer:grad atIndex:0];
}

Adding CAGradient layer but unable to get Gradient effect

Here i am using this code to give a gradient effect but not getting the effect at all.
CAGradientLayer *layer2 = [CAGradientLayer layer];
NSArray *gradientColors = [NSArray arrayWithObjects:(id)[self colorWithHexString:#"3eb79d"].CGColor,(id)[self colorWithHexString:#"3fb65c"].CGColor,(id)[self colorWithHexString:#"3cb7da"].CGColor, nil];
[layer2 setColors:gradientColors];
[layer2 setFrame:cell.userBackgroundView.layer.frame];
[cell.userBackgroundView.layer insertSublayer:layer2 atIndex:0];
cell.userBackgroundView.clipsToBounds = YES;
Try this
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame =cell.userBackgroundView.frame;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor clearColor] CGColor], (id)[[UIColor blackColor] CGColor], nil];
[cell.userBackgroundView.layer insertSublayer:gradient atIndex:0];
Try to change index of sublayer from 0 to -1
[cell.userBackgroundView.layer insertSublayer:layer2 atIndex:-1];
Make sure your userBackgroundView is not covered by another view.
Use
[layer2 setFrame:cell.userBackgroundView.bounds];
instead of
[layer2 setFrame:cell.userBackgroundView.layer.frame];
If you are using autoLayout, make sure to set the frame in viewDidAppear or viewDidLayOutSubviews

Circular gradient color "Not linear" in UIView

I have an issue with the gradient color, I'm not able to make the gradient color appear as circular, it always appear like linear, i need the exact gradient in the following image:
PS: this is the code i use:
UIView *view = [[UIView alloc] initWithFrame:self.view.frame];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.startPoint = CGPointMake(0.0,0.4);
gradient.endPoint = CGPointMake(0.0,0.6);
view.layer.masksToBounds = YES;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:153.0/255.0 green:204.0/255.0 blue:0.0/255.0 alpha:1.0] CGColor], (id)[[UIColor whiteColor] CGColor], nil];
[view.layer insertSublayer:gradient atIndex:0];
[self.view addSubview:view];
There is a CGContextDrawRadialGradient in CGContext. I hope it will help you

CAGradientLayer for different views

I would like to create a color gradient with CAGradientLayer for multiple views with different sizes. I don't know how to define the frame separately:
UIColor *darkOp = [UIColor colorWithRed:0.2f green:0.2f blue:0.27f alpha:1.0];
UIColor *lightOp = [UIColor colorWithRed:0.36f green:0.35f blue:0.42f alpha:1.0];
// Create the gradient
CAGradientLayer *gradient = [CAGradientLayer layer];
// Set colors
gradient.colors = [NSArray arrayWithObjects:
(id)darkOp.CGColor,
(id)lightOp.CGColor,
nil];
//set radius
gradient.cornerRadius = 5.0;
// Set bounds BUT just for one view size
gradient.frame = self.numberRegionView.bounds; //<-- here I can just define one frame size
// Add the gradient to one view
[self.numberRegionView.layer insertSublayer:gradient atIndex:0];
//but how to add the gradient layer to views with different sizes ???
//[self.graphRegionView.layer insertSublayer:gradient atIndex:0]; ???
//[self.barRegionView.layer insertSublayer:gradient atIndex:0]; ???
Thanks!
-(void)setGradientForView:(UIView*)view
{
static UIColor *darkOp = [UIColor colorWithRed:0.2f green:0.2f blue:0.27f alpha:1.0];
static UIColor *lightOp = [UIColor colorWithRed:0.36f green:0.35f blue:0.42f alpha:1.0];
// Create the gradient
CAGradientLayer *gradient = [CAGradientLayer layer];
// Set colors
gradient.colors = [NSArray arrayWithObjects:
(id)darkOp.CGColor,
(id)lightOp.CGColor,
nil];
//set radius
gradient.cornerRadius = 5.0;
// Set bounds BUT just for one view size
gradient.frame = view.bounds; //<-- here I can just define one frame size
// Add the gradient to one view
[view.layer insertSublayer:gradient atIndex:0];
}
Then use this code for your three views:
[self setGradientForView:self.numberRegionView];
[self setGradientForView:self.barRegionView];
[self setGradientForView:self.numberRegionView];

Set a gradient Background to ImageView, rotation

I want to set a gradient Background to my ImageView. I found a solution for that here on Stack Overflow. But it doesn't really satisfy my needs.
I want the gradient to be from left to right. With my the code I found I am only able to fill it from top to bottom.
I create the gradient layer with this code:
+ (CAGradientLayer *)colorGradientWithColor:(UIColor *)color
{
UIColor *colorOne = color;
UIColor *colorTwo = [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:0.0f];
NSArray *colors = [NSArray arrayWithObjects:(id)colorOne.CGColor, colorTwo.CGColor, nil];
NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
NSNumber *stopTwo = [NSNumber numberWithFloat:0.9];
NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, nil];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colors;
gradientLayer.locations = locations;
return gradientLayer;
}
Then I add the layer to my UIImageView:
CAGradientLayer *gradientLayer = [BackgroundGradient colorGradientWithColor:difficultyColor];
gradientLayer.frame = myImageView.bounds;
[myImageView.layer insertSublayer:gradientLayer atIndex:0];
And here is the result:
And here my interface setup:
As you can see, there a two UIImageViews. I want to rotate the layer in the gradient view, so it goes from left to right and not how it is now.
With the following code fragment I am able to rotate the whole ImageView. This only kind of solves my problem, but I don't want that, because it kind of destroys my interface..
myImageView.transform = CGAffineTransformMakeRotation(M_PI*1.5f);
So basically I am searching for a solution to do the gradient from left to right instead from the top to the bottom.
Do you guys have any ideas? I am new to XCode and would appreciate every tip!
This is the result I got from below code. I guess this is what you are trying to achieve
- (CAGradientLayer *)colorGradientWithColor:(UIColor *)color
{
UIColor *colorOne = color;
UIColor *colorTwo = [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:0.0f];
NSArray *colors = [NSArray arrayWithObjects:(id)colorOne.CGColor, colorTwo.CGColor, nil];
NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
NSNumber *stopTwo = [NSNumber numberWithFloat:0.9];
NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, nil];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
[gradientLayer setStartPoint:CGPointMake(0.0, 0.5)];//add these lines
[gradientLayer setEndPoint:CGPointMake(1.0, 0.5)];
gradientLayer.colors = colors;
gradientLayer.locations = locations;
return gradientLayer;
}
Try to rotate your layer before adding it to imageview,using transform.
Use startpoint and endpoint for the gradient layer:
BOOL horizontal = YES;
//(YES for left to right or NO for top to bottom)
gradientLayer.startPoint = horizontal ? CGPointMake(0, 0.5) : CGPointMake(0.5, 0);
gradientLayer.endPoint = horizontal ? CGPointMake(1, 0.5) : CGPointMake(0.5, 1);

Resources