73

I have a UIButton which is very similar to the standard iOS keyboard alphabet button.

I am not sure how to create a shadow only for the bottom layer like how iOS have done.

enter image description here

I use the below code, but I see a shadow on all the side, not just the bottom:

CALayer *buttonLayer = [[CALayer alloc] init];
buttonLayer.shadowColor = [UIColor grayColor].CGColor;
buttonLayer.shadowOffset = CGSizeMake(0.f,1.f);
buttonLayer.masksToBounds = NO;
buttonLayer.shadowOpacity = 1.f;

How can I achieve the same effect?

starball
  • 20,030
  • 7
  • 43
  • 238
Neelesh
  • 3,673
  • 8
  • 47
  • 78

12 Answers12

148

You can mix the cornerRadius and shadow properties. I tested it on iOS 8.

Objective-C:

[self.globeButton setImage:[UIImage imageNamed:@"Globe"] forState:UIControlStateNormal];
self.globeButton.backgroundColor = [UIColor colorWithRed:171 green:178 blue:186 alpha:1.0f];
// Shadow and Radius
self.globeButton.layer.shadowColor = [[UIColor colorWithRed:0 green:0 blue:0 alpha:0.25f] CGColor];
self.globeButton.layer.shadowOffset = CGSizeMake(0, 2.0f);
self.globeButton.layer.shadowOpacity = 1.0f;
self.globeButton.layer.shadowRadius = 0.0f;
self.globeButton.layer.masksToBounds = NO;
self.globeButton.layer.cornerRadius = 4.0f;

Swift:

globeButton.setImage(UIImage(named: "Globe"), for: .normal)
globeButton.backgroundColor = UIColor(red: 171/255, green: 178/255, blue: 186/255, alpha: 1.0)
// Shadow Color and Radius
globeButton.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
globeButton.layer.shadowOffset = CGSize(width: 0.0, height: 2.0)
globeButton.layer.shadowOpacity = 1.0
globeButton.layer.shadowRadius = 0.0
globeButton.layer.masksToBounds = false
globeButton.layer.cornerRadius = 4.0

Result:

UIButton + iOS Keyboard style

ricardopereira
  • 11,118
  • 5
  • 63
  • 81
52

SWIFT 3

import UIKit

class ButtonWithShadow: UIButton {

    override func draw(_ rect: CGRect) {
        updateLayerProperties()
    }

    func updateLayerProperties() {
        self.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
        self.layer.shadowOffset = CGSize(width: 0, height: 3)
        self.layer.shadowOpacity = 1.0
        self.layer.shadowRadius = 10.0
        self.layer.masksToBounds = false
    }

}

button without rounded corners with shadow

!! Only if you do not need corner radius and shadow simultaneously. Otherwise watch this.

Community
  • 1
  • 1
Nike Kov
  • 12,630
  • 8
  • 75
  • 122
18

Be sure to also set shadowRadius to 0:

Given a UIButton property named button set its backing layer properties like this:

self.button.layer.shadowColor = [UIColor grayColor].CGColor;
self.button.layer.shadowOffset = CGSizeMake(0, 1.0);
self.button.layer.shadowOpacity = 1.0;
self.button.layer.shadowRadius = 0.0;
Aaron
  • 7,055
  • 2
  • 38
  • 53
16

I have created IBInspectable extension that will help you.

You can directly assign from storyboard

enter image description here

Swift 5

//MARK:- IBInspectable
extension UIView {
    @IBInspectable var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }

    @IBInspectable var borderWidth: CGFloat {
        get {
            return layer.borderWidth
        }
        set {
            layer.borderWidth = newValue
        }
    }

    @IBInspectable var borderColor: UIColor? {
        get {
            return UIColor(cgColor: layer.borderColor!)
        }
        set {
            layer.borderColor = newValue?.cgColor
        }
    }

    @IBInspectable
    var shadowRadius: CGFloat {
        get {
            return layer.shadowRadius
        }
        set {
            layer.masksToBounds = false
            layer.shadowRadius = newValue
        }
    }

    @IBInspectable
    var shadowOpacity: Float {
        get {
            return layer.shadowOpacity
        }
        set {
            layer.masksToBounds = false
            layer.shadowOpacity = newValue
        }
    }

    @IBInspectable
    var shadowOffset: CGSize {
        get {
            return layer.shadowOffset
        }
        set {
            layer.masksToBounds = false
            layer.shadowOffset = newValue
        }
    }

    @IBInspectable
    var shadowColor: UIColor? {
        get {
            if let color = layer.shadowColor {
                return UIColor(cgColor: color)
            }
            return nil
        }
        set {
            if let color = newValue {
                layer.shadowColor = color.cgColor
            } else {
                layer.shadowColor = nil
            }
        }
    }
}
PinkeshGjr
  • 8,460
  • 5
  • 41
  • 56
12

View bottom shadow swift 4.2

viewTop.layer.shadowOffset = CGSize(width: 0, height: 1)
viewTop.layer.shadowColor = UIColor.lightGray.cgColor
viewTop.layer.shadowOpacity = 1
viewTop.layer.shadowRadius = 5
viewTop.layer.masksToBounds = false
Srinivasan_iOS
  • 972
  • 10
  • 12
  • works like a charm, Add it to a function which takes a parameter like this : `func addShadow(toMy View : UIView){ // above code }` – Yash Bedi May 20 '19 at 10:00
10

You can try with this code: (sorry, i only know swift, not obj c. this code will add bottom shadow on your button.

button.layer.masksToBounds = false
button.layer.shadowColor = UIColor(rgb: 0x000000, alpha: 1.0).CGColor
button.layer.shadowOpacity = 1.0
button.layer.shadowRadius = 0
button.layer.shadowOffset = CGSizeMake(0, 1.0)
TomSawyer
  • 3,711
  • 6
  • 44
  • 79
8

in swift 2.0 add shadow uiview (uibutton) with code before class declaration or in swift file functions:

extension UIView {

    func addShadowView(width:CGFloat=0.2, height:CGFloat=0.2, Opacidade:Float=0.7, maskToBounds:Bool=false, radius:CGFloat=0.5){
         self.layer.shadowColor = UIColor.blackColor().CGColor
         self.layer.shadowOffset = CGSize(width: width, height: height)
         self.layer.shadowRadius = radius
         self.layer.shadowOpacity = Opacidade
         self.layer.masksToBounds = maskToBounds
    }

}

in viewdidload add this code

button.addShadowView()
Pablo Ruan
  • 1,681
  • 1
  • 17
  • 12
5

CornerRadius and shadow don't mix well on the same layer. So you will have to embed your "to be cornered" UIButton inside an UIView. The shadow will be applied on this UIView.

The following code, given as an example, produces the image below it:

import UIKit

class CustomButton: UIButton {

    required init(coder decoder: NSCoder) {
        super.init(coder: decoder)

        backgroundColor = UIColor.whiteColor()
    }

    override func drawRect(rect: CGRect) {
        updateLayerProperties()
    }

    func updateLayerProperties() {
        layer.masksToBounds = true
        layer.cornerRadius = 12.0

        //superview is your optional embedding UIView
        if let superview = superview {
            superview.backgroundColor = UIColor.clearColor()
            superview.layer.shadowColor = UIColor.darkGrayColor().CGColor
            superview.layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 12.0).CGPath
            superview.layer.shadowOffset = CGSize(width: 2.0, height: 2.0)
            superview.layer.shadowOpacity = 1.0
            superview.layer.shadowRadius = 2
            superview.layer.masksToBounds = true
            superview.clipsToBounds = false
        }
    }

}
Shardul
  • 4,266
  • 3
  • 32
  • 50
2

Put this method into your UIView extension and play with offset value

func drawShadow(shadowColor: UIColor = UIColor.black, opacity: Float =
0.3, offset: CGSize, radius: CGFloat = 5, shouldRasterize : Bool = false) {
        self.layer.shadowColor = shadowColor.cgColor
        self.layer.shadowOpacity = opacity
        self.layer.shadowOffset = offset
        self.layer.shadowRadius = radius
        self.layer.shouldRasterize = shouldRasterize
    }
Sajal Gupta
  • 147
  • 2
  • 14
0

To add shadow to a button with corner radius:

final class CustomButton: UIButton {

    private var shadowLayer: CAShapeLayer!

    override func layoutSubviews() {
        super.layoutSubviews()

        if shadowLayer == nil {
            shadowLayer = CAShapeLayer()
            shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 33).cgPath
            if self.backgroundColor != nil {
                shadowLayer.fillColor = self.backgroundColor?.cgColor
            }
            else{
                shadowLayer.fillColor = UIColor.white.cgColor
            }
            shadowLayer.shadowColor = UIColor.gray.cgColor
            shadowLayer.shadowPath = shadowLayer.path
            shadowLayer.shadowOffset = CGSize(width: 0.0, height: 3.0)
            shadowLayer.shadowOpacity = 0.4
            shadowLayer.shadowRadius = 2

            layer.insertSublayer(shadowLayer, at: 0)

        }

    }

}
tushar
  • 293
  • 2
  • 7
0

You can try with this code:

    LoveButtonOutlet.layer.backgroundColor = UIColor.white.cgColor
    LoveButtonOutlet.layer.cornerRadius = 10
    LoveButtonOutlet.layer.borderWidth = 2
    LoveButtonOutlet.layer.borderColor = UIColor.black.cgColor
    LoveButtonOutlet.layer.shadowOffset = CGSize(width: 0, height: 1)
    LoveButtonOutlet.layer.shadowColor = UIColor.darkGray.cgColor
    LoveButtonOutlet.layer.shadowOpacity = 1
    LoveButtonOutlet.layer.shadowRadius = 5
    LoveButtonOutlet.layer.masksToBounds = false
Shahriar Hossain
  • 119
  • 2
  • 13
0
extension UIButton
{
    func setButtonCornerRadiusOnly(getValue:CGFloat)
    {
        self.layer.cornerRadius = getValue
        self.clipsToBounds = true
    }
    
    func setButtonBorderColorAndHeight(getHeight:CGFloat,getColor:UIColor)
    {
        self.layer.borderColor = getColor.cgColor
        self.layer.borderWidth = getHeight
    }
    
    func setBtnWithShadow()
    {
        self.layer.shadowOffset = CGSize(width: 0.5, height: 0.4)
        self.layer.shadowOpacity = 0.5
        self.layer.shadowRadius = 1.5
        self.layer.cornerRadius = self.frame.size.height/2
        self.layer.masksToBounds =  false
    }
}
Davender Verma
  • 503
  • 2
  • 12