UIButton shadow layer effect - ios

I am creating a UIButton similar to this image:
I tried it by using following code:
+(void)createShadowOnView:(UIView *)view color:(UIColor *)color width:(CGFloat)width height:(CGFloat)height shadowOpacity:(CGFloat)shadowOpacity andShadowRadius:(CGFloat)radius{
view.layer.masksToBounds = NO;
view.layer.shadowColor = color.CGColor;
view.layer.shadowOffset = CGSizeMake(width,height);
view.layer.shadowOpacity = shadowOpacity;
[view.layer setShadowRadius:radius];
}
I was able to achieve this:
I want shadow effect on Button to be kept only on bottom part.
How can I achieve desired effect.

Maybe you should set view's backgroundcolor, so the title has no shadow, you can set view.layer.shadowOffset to change the shadow size.
UIButton *customBTn = [UIButton buttonWithType:UIButtonTypeCustom];
customBTn.backgroundColor = [UIColor whiteColor];
customBTn.frame = CGRectMake(100, 100, 200, 50);
[customBTn setTitle:#"Sign Up" forState:UIControlStateNormal];
[customBTn setTitleColor:[UIColor colorWithRed:1/255.0 green:168/255.0 blue:244/255.0 alpha:1.0] forState:UIControlStateNormal];
customBTn.layer.borderColor = [UIColor colorWithRed:1/255.0 green:168/255.0 blue:244/255.0 alpha:1.0].CGColor;
customBTn.layer.borderWidth = 2;
customBTn.layer.cornerRadius = 25;
customBTn.layer.shadowColor = [UIColor lightGrayColor].CGColor;
customBTn.layer.shadowOffset = CGSizeMake(0,8);
customBTn.layer.shadowOpacity = 0.9;
[self.view addSubview:customBTn];
Output :-

Only issue with your code is you missed to set background colour for your sign up button. Use this code,
self.signUpButton.backgroundColor = [UIColor whiteColor];
[UIView createShadowOnView:self.signUpButton color:[UIColor lightGrayColor] width:0 height:2 shadowOpacity:0.3 andShadowRadius:0];

Preview:
Code:
UIButton *buttonWithShadow = [UIButton buttonWithType:UIButtonTypeCustom];
[buttonWithShadow setFrame:CGRectMake(10.0f, 10.0f, 300.0f, 50.0f)];
[buttonWithShadow setTitle:#"SIGN UP" forState:UIControlStateNormal];
[buttonWithShadow setTitle:#"SIGN UP" forState:UIControlStateHighlighted];
[buttonWithShadow.titleLabel setFont:[UIFont boldSystemFontOfSize:15.0f]];
[buttonWithShadow setTitleColor:[UIColor colorWithRed:1.0f/255.0 green:168.0f/255.0 blue:244.0f/255.0 alpha:1.0f] forState:UIControlStateNormal];
[buttonWithShadow setBackgroundColor:[UIColor whiteColor]];
[buttonWithShadow.layer setBorderColor:[UIColor colorWithRed:1.0f/255.0 green:168.0f/255.0 blue:244.0f/255.0 alpha:1.0f].CGColor];
[buttonWithShadow.layer setBorderWidth:2.0f];
[buttonWithShadow.layer setCornerRadius:(buttonWithShadow.frame.size.height / 2.0f)];
[buttonWithShadow.layer setShadowColor:[UIColor lightGrayColor].CGColor];
[buttonWithShadow.layer setShadowOpacity:0.3f];
[buttonWithShadow.layer setShadowRadius:0.0f];
[buttonWithShadow.layer setShadowOffset:CGSizeMake(0.0f,2.0f)];
[buttonWithShadow.layer setMasksToBounds:NO];
[self.view addSubview:buttonWithShadow];

Related

UIButton used to work until I added UIlabel

I tried to label a UIbutton which used to work until I added a UIlabel layer.
At first the button looked like this and later I filled the space either side of the label thus
When I click either button the following error report is logged:
unexpected nil window in _UIApplicationHandleEventFromQueueEvent, _windowServerHitTestWindow: <UIWindow: 0x7fe460e338d0; frame = (0 0; 320 480); opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7fe460e326a0>; layer = <UIWindowLayer: 0x7fe460e33d80>>
The button works if I click above the 4 letters or the ^ symbols.
Adding the label layer seems to effectively mask the UIButton. The hot spot (i.e. where the button works) seems to be above the letters or the ^ symbols. Can anyone explain why this might be happening ?
GlobalView.h file imports Quartz.Core/QuartzCore.h and UIKit/UIKit.h
Here’s the code in GlobalView.m
[UIButton buttonWithType:UIButtonTypeSystem];
UIButton *helpButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
helpButton.frame = CGRectMake(72.0f, 472.0f, 188.0f, 32.0f);
helpButton.layer.cornerRadius = 10;
[helpButton.layer setBorderColor:[[UIColor whiteColor] CGColor]];
[[helpButton layer] setBorderWidth:0.5f];
[helpButton addTarget:self action:#selector(goToHelp) forControlEvents:UIControlEventTouchUpInside];
UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(72.0f, 472.0f, 188.0f, 32.0f);
label.text=#“help”;
[label setTextAlignment: NSTextAlignmentCenter];
label.textColor=[UIColor whiteColor];
[label.layer setBorderColor:[[UIColor whiteColor] CGColor]];
[helpButton addSubview:label];
[self.view addSubview:helpButton];
Is the error log hinting that there is something I can do to recognise a tap gesture ? or is it better to try and get the UIButton to respond ?
CHANGE #1
The same problem occurs when I use setTitle to label the button
[UIButton buttonWithType:UIButtonTypeSystem];
UIButton *helpButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
helpButton.frame = CGRectMake(72.0f, 472.0f, 188.0f, 32.0f);
[helpButton setTitle: #"Transposed Dekany" forState: UIControlStateNormal];
helpButton.layer.cornerRadius = 10;
[helpButton.layer setBorderColor:[[UIColor whiteColor] CGColor]];
[[helpButton layer] setBorderWidth:0.5f];
[helpButton addTarget:self action:#selector(goToHelp) forControlEvents:UIControlEventTouchUpInside];
UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(0,0,188,32)];
[label.layer setBorderColor:[[UIColor whiteColor] CGColor]];
[helpButton addSubview:label];
[self.view addSubview:helpButton];
CHANGE #2
UIButton *helpButton = [UIButton buttonWithType:UIButtonTypeCustom];
[helpButton setTitleColor:[UIColor whiteColor] forState: UIControlStateNormal];
[helpButton setTitle: #"^^^^^^^Help^^^^^^^^^" forState: UIControlStateNormal];
helpButton.frame = CGRectMake(72.0f, 472.0f, 188.0f, 32.0f); //same width and height
helpButton.layer.cornerRadius = 10;
[helpButton.layer setBorderColor:[[UIColor whiteColor] CGColor]];
[[helpButton layer] setBorderWidth:0.5f];
helpButton.clipsToBounds = YES;
[helpButton addTarget:self action:#selector(goToHelp) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:helpButton];

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];
}

Button Title changing unexpectedly in UIButton

I have a UIButton created with the following code:
applyButton= [[UIButton alloc] initWithFrame:CGRectMake(75, 636, 150, 50)];
[applyButton titleColorForState:UIControlStateNormal];
[applyButton setTitle:#"MyTitle" forState:UIControlStateNormal];
applyButton.titleLabel.textColor=[UIColor lightGrayColor];
[[applyButton layer] setBorderWidth:2.0f];
[[applyButton layer] setBorderColor:[[UIColor lightGrayColor] CGColor]];
applyButton.layer.cornerRadius = 10;
[applyButton addTarget:self action:#selector(saveSettingsToNSUser:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:applyButton];
The button appears with "MyTitle" in light gray colour initially.
But when i presses it the title colour turns white and the "saveSettingsToNSUser" function is called.There is NOTHING inside the function "saveSettingsToNSUser" which affects the button. I don't understand what is happening. Am i missing something?
You should use setTitleColor:forState: to set title label color.
[applyButton setTitleColor: [UIColor lightGrayColor] forState: UIControlStateNormal];
applyButton= [[UIButton alloc] initWithFrame:CGRectMake(75, 636, 150, 50)];
//set title
[applyButton setTitle:#"MyTitle" forState:UIControlStateHighlighted];
[applyButton titleColorForState:UIControlStateNormal];
[applyButton setTitle:#"MyTitle" forState:UIControlStateNormal];
applyButton.titleLabel.textColor=[UIColor lightGrayColor];
[[applyButton layer] setBorderWidth:2.0f];
[[applyButton layer] setBorderColor:[[UIColor lightGrayColor] CGColor]];
applyButton.layer.cornerRadius = 10;
[applyButton addTarget:self action:#selector(saveSettingsToNSUser:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:applyButton];

UIButton border that changes thickness when selected

I have a subclassed UIButton
- (void)configureButton
{
self.titleLabel.font = [UIFont systemFontOfSize:18.0f];
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
CALayer *border = [CALayer layer];
border.backgroundColor = [UIColor whiteColor].CGColor;
border.frame = CGRectMake(0, self.frame.size.height, self.frame.size.width, 1.0);
[self.layer addSublayer:border];
}
- (void)setSelected:(BOOL)selected
{
[super setSelected:selected];
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
// remove all layers ?
if (selected) {
CALayer *border = [CALayer layer];
border.backgroundColor = [UIColor whiteColor].CGColor;
border.frame = CGRectMake(0, self.frame.size.height, self.frame.size.width,3.0);
[self.layer addSublayer:border];
self.titleLabel.font = [UIFont boldSystemFontOfSize:18.0f];
} else {
CALayer *border = [CALayer layer];
border.backgroundColor = [UIColor whiteColor].CGColor;
border.frame = CGRectMake(0, self.frame.size.height, self.frame.size.width,1.0);
[self.layer addSublayer:border];
self.titleLabel.font = [UIFont systemFontOfSize:18.0f];
}
}
The default state of the button has a 1.0 bottom border. When it is selected, the border should become 3.0. How can I clear the previously added layer and re add a 1.0 border when a user toggles a button?
I believe there is an easier way to do what you need. If you subclass the UIButton just because you just want to have different types button border, you can try a different way but a lot easier.
Use 2 different button background image, one with border 1 and another with border 3.
[self.button setBackgroundImage:[UIImage imageNamed:#"ImageWithBorder1"] forState:UIControlStateNormal];
[self.button setBackgroundImage:[UIImage imageNamed:#"ImageWithBorder3"] forState:UIControlStateHighlighted];
[self.button setBackgroundImage:[UIImage imageNamed:#"ImageWithBorder3"] forState:UIControlStateSelected];
With an additional button image, it might just take extra 10 kb on your project.

Touch another UITextField don't work (sometimes)

I have 2 textfields. On startup I can switch between lbl and lbl2. But after the first click only lbl is working, you have to tap 10(+/-) times on lbl2 before the cursor goes to that textfield. Whats going on?
- (void)viewWillAppear:(BOOL)animated
{
UITextField *lbl = [[UITextField alloc] initWithFrame:CGRectMake(24, 397, 266, 30)];
[lbl setPlaceholder:#"E-mailadres"];
[lbl setValue:[UIColor whiteColor] forKeyPath:#"_placeholderLabel.textColor"];
[lbl setBackgroundColor:[UIColor clearColor]];
lbl.textColor = [UIColor whiteColor];
[[self view] addSubview:lbl];
CALayer* layer = [lbl layer];
CALayer *bottomBorder = [CALayer layer];
bottomBorder.borderColor = [UIColor whiteColor].CGColor;
bottomBorder.borderWidth = 1;
bottomBorder.frame = CGRectMake(-1, layer.frame.size.height-1, layer.frame.size.width, 1);
[bottomBorder setBorderColor:[UIColor whiteColor].CGColor];
[layer addSublayer:bottomBorder];
UITextField *lbl2 = [[UITextField alloc] initWithFrame:CGRectMake(24, 450, 266, 30)];
[lbl2 setPlaceholder:#"Wachtwoord"];
[lbl2 setValue:[UIColor whiteColor] forKeyPath:#"_placeholderLabel.textColor"];
[lbl2 setBackgroundColor:[UIColor clearColor]];
lbl2.textColor = [UIColor whiteColor];
lbl2.secureTextEntry = YES;
[[self view] addSubview:lbl2];
CALayer* layer2 = [lbl2 layer];
CALayer *bottomBorder2 = [CALayer layer];
bottomBorder2.borderColor = [UIColor whiteColor].CGColor;
bottomBorder2.borderWidth = 1;
bottomBorder2.frame = CGRectMake(-1, layer2.frame.size.height-1, layer2.frame.size.width, 1);
[bottomBorder2 setBorderColor:[UIColor whiteColor].CGColor];
[layer2 addSublayer:bottomBorder2];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
myButton.frame = CGRectMake(24, 500, 266, 30); // position in the parent view and set the size of the button
[myButton setTitle:#"INLOGGEN" forState:UIControlStateNormal];
[myButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
// add targets and actions
// add to a view
[[self view] addSubview:myButton];
CALayer *layer3 = myButton.layer;
layer3.backgroundColor = [[UIColor whiteColor] CGColor];
layer3.borderColor = [[UIColor whiteColor] CGColor];
layer3.borderWidth = 1.0f;
layer3.opacity = 0.6;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}
It appears neither text field was given a delegate. I'm not sure you can use them without one - I never tried. If you don't have a delegate how would you dismiss the keyboard at the end of the editing session?

Resources