iOS linear gradient on UIButton not displaying properly - ios

I am trying to add a gradient to my custom UIButton, but when I run it, the button appears transparent instead of showing the desired gradient.
Here is my code:
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.titleLabel.font = [UIFont fontWithName:#"SFUIDisplay-Medium" size:16];
[button setTitleColor:[UIColor whiteColor]
forState:UIControlStateNormal];
button.layer.cornerRadius = [UIButton cornerRadius];
button.contentEdgeInsets = UIEdgeInsetsMake(13, 0, 13, 0);
button.frame = CGRectMake(50, 50, 100, 40); //this line is new
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = button.layer.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor lightGrayColor].CGColor,
(id)[UIColor blackColor].CGColor,
nil];
gradientLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:1.0f],
nil];
gradientLayer.cornerRadius = button.layer.cornerRadius;
gradientLayer.startPoint = CGPointMake(0, 0.5); //this line is new
gradientLayer.endPoint = CGPointMake(1, 0.5); //this line is new
[button.layer addSublayer:gradientLayer];
button.translatesAutoresizingMaskIntoConstraints = NO;
[button setTitle:#"Test"
forState:UIControlStateNormal];
[button constrainHeight:56];
[button addTarget:self
action:#selector(doAction)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
If I add in this line:
button.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0];
then the button looks like this.

Your code works fine after I have assigned frame, e.g.:
button.frame = CGRectMake(50, 50, 100, 40);
And added to view controller's view, e.g.:
[self.view addSubview:button];

First, try adding your button to the view. Then, it doesn't look like you are setting a start point and end point. For a linear gradient, try something like:
[self.view addSubview: button];
gradientLayer.startPoint = CGPointMake(x: 0, y: 0.5);
gradientLayer.endPoint = CGPointMake(x: 1, y: 0.5);
This configuration will ensure the gradient starts at the middle of the left side and end at the middle of the right side. You can tinker with the values for different types of gradients using the idea described below:
(0, 0) || (1, 0)
||
=========================
||
(1, 0) || (1, 1)

Related

Programatically adding a iOS 6 look alike gradient UIButton

I am trying to draw a red button programmatically and want look and feel exactly that for an iOS6 button (including gradient effect).
I am doing this to support one of my application on iOS 6. I tried with custom button but no able to reach the milestone. Appreciate any quick help.
Here is what I have done in my custom 'UITableViewCell' class:
UIButton *myRedButton = [[UIButton alloc] initWithFrame:CGRectMake(CGRectGetMaxX(self.contentView.bounds) - 100, 0.0, 100, 35)];
myRedButton.titleLabel.font = [UIFont systemFontOfSize:12];
myRedButton.backgroundColor = [UIColor colorWithRed:194.0/255.0 green:21.0/255.0 blue:35.0/255.0 alpha:1.0];
myRedButton.layer.cornerRadius = 8.0;
myRedButton.clipsToBounds = YES;
[self.contentView addSubview:myRedButton];
For the benefit of others (in case some one is looking around for similar context) here is how I achieved it:
UIButton *myRedButton = [[UIButton alloc] initWithFrame:autoReverseButtonFrame];
myRedButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
myRedButton.layer.cornerRadius = 8.0;
myRedButton.clipsToBounds = YES;
myRedButton.layer.borderColor = [UIColor blackColor].CGColor;
self.autoReverseButton.layer.borderWidth = 1.0;
CGColorRef topColor = [UIColor colorWithRed:240.0/255.0 green:127.0/255.0 blue:133.0/255.0 alpha:1.0].CGColor;
CGColorRef bottomColor = [UIColor colorWithRed:194.0/255.0 green:21.0/255.0 blue:35.0/255.0 alpha:1.0].CGColor;
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = myRedButton.bounds;
gradient.cornerRadius = myRedButton.layer.cornerRadius;
gradient.colors = #[(__bridge id)topColor, (__bridge id)bottomColor];
[myRedButton.layer insertSublayer:gradient atIndex:0];

iOS: UIButton draw circle border in iOS

I need to draw a circle like border outside UIButton. Below is the attach image and code. I also need to show text below button. Following code will add image and text beneath that. But how do I have layer.
UIButton *imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[imageButton setBackgroundImage:image forState:UIControlStateNormal];
imageButton.translatesAutoresizingMaskIntoConstraints = NO;
imageButton.backgroundColor = [UIColor clearColor];
[imageButton setTitle:title forState:UIControlStateNormal];
imageButton.titleLabel.textAlignment = NSTextAlignmentCenter;
imageButton.titleLabel.font = [UIFont fontWithName:#"OpenSans" size:fon];
[imageButton setTitleEdgeInsets:UIEdgeInsetsMake(95, 0.0f, 0.0f, 0.0f)];
[imageButton setTitleColor:[UIColor iconTextColor] forState:UIControlStateNormal];
[imageButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
set the button width and height ex : width =100 and height = 100, should be same if you want a round then,
imageButton.layer.cornerRadius = 50 // this value should be half from width or height (width = height)
imageButton.layer.masksToBounds = YES
//if you want border with above
imageButton.layer.borderWidth = 1;
imageButton.layer.borderColor = [[UIColor blackColor] CGColor];
You can do something like this.
borderView = UIView()
yourButton = UIButton()
borderView.frame.size.width = yourButton.frame.size.width + 1
borderView.layer.cornerRadius = borderView.frame.size.width/2
borderView.clipToBounds = true
borderView.backgroundColor = UIColor.clearColor()
borderView.layer.borderWidth = 1
borderView.layer.borderColor = UIColor.blueColor()

Shadow on UIButton text only (not background)

I have a set of UIButtons with background colors. when the user taps one, I want only the button's text to have a shadow all around it (to show that it has been selected). However, when I add the shadow, the shadow appears over the whole button (background and all), and not just the text. Is there an easier workaround to this than just adding a UILabel over a blank button?
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
...
[button setBackgroundColor:[UIColor blueColor]];
[button.layer setShadowRadius:8.0];
[button.layer setShadowColor:[[UIColor orangeColor] CGColor]];
[button.layer setShadowOpacity:0];
...
Here is the simple way to add shadow to the button title with shadow radius property available in Objective-C:
#import <QuartzCore/QuartzCore.h>
button.titleLabel.layer.shadowOffset = CGSizeMake(2.0, 2.0);
button.titleLabel.layer.shadowColor = [UIColor colorWithWhite:0.1 alpha:0.7].CGColor;
button.titleLabel.layer.shadowRadius = 2.0;
button.titleLabel.layer.shadowOpacity = 1.0;
button.titleLabel.layer.masksToBounds = NO;
Swift ..
Say you override the UIButton class ..
titleLabel!.layer.shadowColor = UIColor.black.cgColor
titleLabel!.layer.shadowOffset = CGSize(width: -0.5, height: 0.5)
titleLabel!.layer.shadowOpacity = 1.0
titleLabel!.layer.shadowRadius = 0
titleLabel!.layer.masksToBounds = false
You need to use setTitleShadowColor: forState: and shadowOffset property of UIButton.
below code will add shadow only to button label whenever user tap on button.
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setBackgroundColor:[UIColor blueColor]];
button.frame = CGRectMake(50, 70, 200, 100);
[button setTitle:#"Test Button" forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont systemFontOfSize:45]];
[button setTitleShadowColor:[UIColor redColor] forState:UIControlStateHighlighted];
[button.titleLabel setShadowOffset:CGSizeMake(2.0, 2.0)];
Hope this will help.
Just set the shadow on the titleLabel property of the UIButton rather than what you're doing now.
eg
button.titleLabel.shadowColor = ((selectionState) ?[UIColor orangeColor] : [UIColor clearColor] );
button.titleLabel.shadowOffset = CGSizeMake (1.5,1.5);
For 2018
This does not work. Use the answer of #Userich
One way to do this is to use attributed strings for the normal and highlighted titles. You can create an NSShadow object, and assign that as the value for the NSShadowAttributeName. This gives you control over the properties of the shadow. To keep the title from dimming, you should set the button type to Custom instead of System.
- (void)viewDidLoad {
[super viewDidLoad];
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor darkGrayColor];
shadow.shadowOffset = CGSizeMake(2, 2);
shadow.shadowBlurRadius = 2;
NSString *titleString = #"Title";
NSAttributedString *normalTitle = [[NSAttributedString alloc] initWithString:titleString];
NSAttributedString *highlightedTitle = [[NSAttributedString alloc] initWithString:titleString attributes:#{NSShadowAttributeName:shadow}];
[self.button setAttributedTitle:normalTitle forState:UIControlStateNormal];
[self.button setAttributedTitle:highlightedTitle forState:UIControlStateHighlighted];
}

text transparency|color gradient

I am trying to put transparency (or a color gradient) on the title of an UIButton. I don't know how do that. I have tried to simply put a clearColor on the titleColor but we only see the background color.
So i hope that there is someone here who will be an amazing idea for my problem.
My solution
self.loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.loginButton.backgroundColor= [UIColor whiteColor];
self.loginButton.frame = CGRectMake(self.signUpButton.left,
0,
self.signUpButton.frame.size.width,
self.signUpButton.frame.size.height);
[self.loginButton.layer setBackgroundColor:[[UIColor blackColor] CGColor]];
self.loginButton.layer.borderColor = [[UIColor whiteColor] CGColor];
self.loginButton.layer.borderWidth = 1.0f;
self.loginButton.layer.cornerRadius = 3.0f;
[self.loginButton addTarget:self action:#selector(loginButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
self.loginButtonLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
self.loginButtonLabel.font = [UIFont fontWithName:#"OpenSans-Light" size:16.0f];
self.loginButtonLabel.textColor = [UIColor whiteColor];
self.loginButtonLabel.text = #"Connexion";
[self.loginButtonLabel sizeToFit];
UIColor *topColor = [UIColor blueColor];
UIColor *bottomColor = [UIColor orangeColor];
self.gradientView = [[UIView alloc] initWithFrame:self.loginButtonLabel.frame];
[self.loginButton addSubview:self.gradientView];
[self.loginButton sendSubviewToBack:self.gradientView];
[self.loginButton addSubview:self.loginButtonLabel];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.gradientView.frame;
gradient.colors = [NSArray arrayWithObjects:(id)topColor.CGColor, (id)bottomColor.CGColor, nil];
gradient.startPoint = CGPointMake(0, 0.5);
gradient.endPoint = CGPointMake(1, 0.5);
[self.gradientView.layer addSublayer:gradient];
self.gradientView.layer.mask = self.loginButtonLabel.layer;
self.gradientView.layer.masksToBounds = YES;
self.gradientView.center = CGPointMake(self.loginButton.width / 2, self.loginButton.height / 2);
[self.view addSubview:self.loginButton];
But Now i need to put the gradient on the border. Any idea ?
So my solution is to create a custom button with an UILabel. I will use an UIView with a gradient for color the text.
The solution :
self.loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.loginButton.backgroundColor= [UIColor whiteColor];
self.loginButton.frame = CGRectMake(self.signUpButton.left,
0,
self.signUpButton.frame.size.width,
self.signUpButton.frame.size.height);
[self.loginButton.layer setBackgroundColor:[[UIColor blackColor] CGColor]];
self.loginButton.layer.borderColor = [[UIColor whiteColor] CGColor];
self.loginButton.layer.borderWidth = 1.0f;
self.loginButton.layer.cornerRadius = 3.0f;
[self.loginButton addTarget:self action:#selector(loginButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
self.loginButtonLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
self.loginButtonLabel.font = [UIFont fontWithName:#"OpenSans-Light" size:16.0f];
self.loginButtonLabel.textColor = [UIColor whiteColor];
self.loginButtonLabel.text = #"Connexion";
[self.loginButtonLabel sizeToFit];
UIColor *topColor = [UIColor blueColor];
UIColor *bottomColor = [UIColor orangeColor];
self.gradientView = [[UIView alloc] initWithFrame:self.loginButtonLabel.frame];
[self.loginButton addSubview:self.gradientView];
[self.loginButton sendSubviewToBack:self.gradientView];
[self.loginButton addSubview:self.loginButtonLabel];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.gradientView.frame;
gradient.colors = [NSArray arrayWithObjects:(id)topColor.CGColor, (id)bottomColor.CGColor, nil];
gradient.startPoint = CGPointMake(0, 0.5);
gradient.endPoint = CGPointMake(1, 0.5);
[self.gradientView.layer addSublayer:gradient];
self.gradientView.layer.mask = self.loginButtonLabel.layer;
self.gradientView.layer.masksToBounds = YES;
self.gradientView.center = CGPointMake(self.loginButton.width / 2, self.loginButton.height / 2);
[self.view addSubview:self.loginButton];

UIButton with GradientLayer obscures image and darkens gradient

I have an UIButton here where I'd like to have a gradient as the background below the image (symbol with transparent background), but I'm facing two different problems.
First of the CAGradientLayer seems to overlay on top of the image no matter how I try to add it, obscuring the image completely.
Secondly the gradient itself seems to be darkened a lot, like the button was disabled, which it isn't.
Here's my code:
self.backButton = [[UIButton alloc] initWithFrame:CGRectMake(15, 35, 28, 28)];
[backButton addTarget:self
action:#selector(goBack)
forControlEvents:UIControlEventTouchUpInside];
[backButton setBackgroundColor:[UIColor clearColor]];
CAGradientLayer *buttonGradient = [CAGradientLayer layer];
buttonGradient.frame = backButton.bounds;
buttonGradient.colors = [NSArray arrayWithObjects:
(id)[[UIColor colorWithRed:.0
green:.166
blue:.255
alpha:1] CGColor],
(id)[[UIColor colorWithRed:.0
green:.113
blue:.255
alpha:1] CGColor],
nil];
[buttonGradient setCornerRadius:backButton.frame.size.width / 2];
[backButton.layer insertSublayer:buttonGradient
atIndex:0];
[backButton setImage:[UIImage imageNamed:#"backarrow.png"]
forState:UIControlStateNormal];
[backButton setEnabled:NO];
[topbarView addSubview:backButton];
So I managed to get around this by doing a [button bringSubviewToFront:button.imageView] after adding the gradient. Seems that no matter what I do the new layer will add on top of the imageView, so I need to push that to the front afterwards.
Objective-C:
[button bringSubviewToFront:button.imageView]
Swift 4.1:
button.bringSubview(toFront:button.imageView!)
Alternatively, you can insert the gradient layer below the image view's layer
CAGradientLayer* gradient = [CAGradientLayer layer];
// ...
[button.layer insertSublayer:gradient below:button.imageView.layer];
SWIFT 3
Here goes an example: (Based on Neil answer)
let layer = CAGradientLayer()
layer.frame = CGRect(x: 0, y: 0, width: myButtonOutlet.layer.frame.size.width, height: myButtonOutlet..layer.frame.size.height)
layer.colors = [UIColor.white.cgColor, pixelColorReceta.cgColor]
layer.masksToBounds = true
layer.cornerRadius = myButtonOutlet.layer.cornerRadius
myButtonOutlet.layer.insertSublayer(layer, below: myButtonOutlet..imageView?.layer)
Happy coding :)
Swift 3
You can move the image above the gradient:
button.imageView?.layer.zPosition = 1
or insert the gradient under the image:
button.layer.insertSublayer(gradientLayer, below: button.imageView?.layer)

Resources