76

I would like to add a drop shadow to a UIButton. I tried to use self.layer.shadow* properties. Those properties work in UIView, but they behave differently in UIButton. I would really appreciate it if I could get any pointers to draw the drop shadow. Thank you!

self.layer.cornerRadius = 8.0f;
self.layer.masksToBounds = YES;
self.layer.borderWidth = 1.0f;

self.layer.shadowColor = [UIColor greenColor].CGColor;
self.layer.shadowOpacity = 0.8;
self.layer.shadowRadius = 12;
self.layer.shadowOffset = CGSizeMake(12.0f, 12.0f);
Chris Frost
  • 1,019
  • 2
  • 9
  • 7
  • The Core Animation Guide, http://developer.apple.com/mac/library/documentation/cocoa/conceptual/CoreAnimation_guide/Articles/LayerVisProps.html, says: iPhone OS Note: As a performance consideration, iPhone OS does not support the shadowColor, shadowOffset, shadowOpacity, and shadowRadius properties. Dang. – d_CFO Apr 27 '10 at 20:13
  • This properties are now supported since iOS 3.2. Regards, – Quentin Aug 11 '10 at 08:53

5 Answers5

100

There is only one tiny mistake in the question that causes the shadow to not be displayed: masksToBounds:YES also masks the shadow! Here's the correct code:

self.layer.cornerRadius = 8.0f;
self.layer.masksToBounds = NO;
self.layer.borderWidth = 1.0f;

self.layer.shadowColor = [UIColor greenColor].CGColor;
self.layer.shadowOpacity = 0.8;
self.layer.shadowRadius = 12;
self.layer.shadowOffset = CGSizeMake(12.0f, 12.0f);

Unfortunately, this means we cannot mask the content and have a shadow at the same time without tricks.

Remember to #import <QuartzCore/QuartzCore.h>.

fzwo
  • 9,724
  • 3
  • 35
  • 56
62

Here's a easy solution if you are using a UIButton:

#import <QuartzCore/QuartzCore.h>

button.imageView.layer.cornerRadius = 7.0f;
button.layer.shadowRadius = 3.0f;
button.layer.shadowColor = [UIColor blackColor].CGColor;
button.layer.shadowOffset = CGSizeMake(0.0f, 1.0f);
button.layer.shadowOpacity = 0.5f;
button.layer.masksToBounds = NO;

Just got it working, and figured it was worth posting. Hope that Helps!

msgambel
  • 7,210
  • 4
  • 41
  • 60
39

Here's a subclass that not only creates the drop shadow, but the button animates down when you press on it.

//
//  ShadowButton.h

#import <Foundation/Foundation.h>

@interface ShadowButton : UIButton {
}

@end

//
//  ShadowButton.m

#import "ShadowButton.h"
#import <QuartzCore/QuartzCore.h>

@implementation ShadowButton

-(void)setupView{

    self.layer.shadowColor = [UIColor blackColor].CGColor;
    self.layer.shadowOpacity = 0.5;
    self.layer.shadowRadius = 1;
    self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f);

}

-(id)initWithFrame:(CGRect)frame{
    if((self = [super initWithFrame:frame])){
        [self setupView];
    }

    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    if((self = [super initWithCoder:aDecoder])){
        [self setupView];
    }

    return self;
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    self.contentEdgeInsets = UIEdgeInsetsMake(1.0,1.0,-1.0,-1.0);
    self.layer.shadowOffset = CGSizeMake(1.0f, 1.0f);
    self.layer.shadowOpacity = 0.8;

    [super touchesBegan:touches withEvent:event];

}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    self.contentEdgeInsets = UIEdgeInsetsMake(0.0,0.0,0.0,0.0);
    self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f);
    self.layer.shadowOpacity = 0.5;

    [super touchesEnded:touches withEvent:event];

}

@end
avance
  • 1,971
  • 2
  • 21
  • 23
3

You can create a subclass and configure its values in Xcode

Below is an example:

import UIKit
import QuartzCore

@IBDesignable
class CustomButton: UIButton {

@IBInspectable var cornerRadius: CGFloat = 0 {
    didSet {
        layer.cornerRadius = cornerRadius
    }
}

@IBInspectable var borderWidth: CGFloat = 0 {
    didSet {
        layer.borderWidth = borderWidth
    }
}

@IBInspectable var borderColor: UIColor = UIColor.gray {
    didSet {
        layer.borderColor = borderColor.cgColor
    }
}

@IBInspectable var shadowColor: UIColor = UIColor.gray {
    didSet {
        layer.shadowColor = shadowColor.cgColor
    }
}

@IBInspectable var shadowOpacity: Float = 1.0 {
    didSet {
        layer.shadowOpacity = shadowOpacity
    }
}

@IBInspectable var shadowRadius: CGFloat = 1.0 {
    didSet {
        layer.shadowRadius = shadowRadius
    }
}

@IBInspectable var masksToBounds: Bool = true {
    didSet {
        layer.masksToBounds = masksToBounds
    }
}

@IBInspectable var shadowOffset: CGSize = CGSize(width: 12, height: 12) {
    didSet {
        layer.shadowOffset = shadowOffset
    }
}


 }
temp
  • 623
  • 1
  • 8
  • 21
Abdul Yasin
  • 3,292
  • 1
  • 25
  • 40
2

You can subclass UIButton and overwrite the drawRect: method and add manually a drop shadow. That's much more work and you should now a few things about quartz 2d, but the result is exactly what you want. Otherwise you could just add an image, but I prefere to subclass UIButton, because it is very flexible regarding the size of the button, it's more general.

burki
  • 2,666
  • 4
  • 33
  • 49