32

I've created an uiview in my xib with background color as clear color. When I apply the shadow on the layer of the view, the shadow is not appearing. But when i set the background color other than clear color, shadow is showing. Please help.

this is my code

self.cView.layer.shadowColor=[UIColor whiteColor].CGColor;
self.cView.layer.shadowOffset=CGSizeZero;
self.cView.layer.shadowRadius=30.0;
self.cView.layer.shadowOpacity=1.0;
self.cView.layer.cornerRadius=10.0;
Nekto
  • 17,837
  • 1
  • 55
  • 65
Mukunda
  • 389
  • 1
  • 3
  • 9

3 Answers3

41

The problem is, that shadow actually takes into account the 'upper' layer. If there's nothing on it there will be no shadow: How Shadows Work

EDIT:

There is this recipe copied from paste bin

view.layer.shadowColor = [UIColor colorWithWhite:.5 alpha:1].CGColor;
view.layer.shadowRadius = 4.0f;
view.layer.shadowPath = CGPathCreateWithRect(CGRectMake(0, 0, 50, 50), NULL);
view.layer.shadowOpacity = 1.0f;
view.layer.shadowOffset = CGSizeMake(1, 1);

But I doubt this will be of any use to you: the result is a view 'painted' with color of a shadow and a shadow around it.

Rok Jarc
  • 18,765
  • 9
  • 69
  • 124
  • 1
    Yes, shadows only occur when the view is opaque or there is some content in it. Setting clear color is like setting the view transparent. – Mukunda Oct 17 '12 at 06:43
  • The down side is, UIView.animate does not work with shadowPath. – James L Nov 04 '17 at 02:59
  • @JamesL , it works perfectly. Ignore this incorrect answer and see the code by Demosthese – Fattie Oct 12 '19 at 13:34
18

If you specify shadowPath property

shadowView.layer.shadowPath =
  UIBezierPath(
   roundedRect: shadowView.bounds,
   cornerRadius: 10).cgPath

(Or whatever corner radius is desired.)

it will work even with .clear backgroundColor.

Note that you of course have to do this in layoutSubviews of the view in question.

Here's an actual full working example:

import UIKit

@IBDesignable class LonelyShadow: UIView {

    let corner: CGFloat = 20

    override init(frame: CGRect) {
        super.init(frame: frame)
        common()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        common()
    }

    private func common() {

        backgroundColor = .clear
        clipsToBounds = false

        layer.shadowColor = UIColor.yourColor.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 25)
        layer.shadowOpacity = 0.3
        layer.shadowRadius = 40
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        layer.shadowPath = UIBezierPath(
          roundedRect: bounds, cornerRadius: corner).cgPath
    }
}
Fattie
  • 27,874
  • 70
  • 431
  • 719
Senõr Ganso
  • 1,694
  • 16
  • 23
3

Equivalent to @Rok Jark's answer in Swift 4:

self.layer.shadowColor = UIColor(white: 0.5, alpha: 1).cgColor
self.layer.shadowRadius = 4.0
self.layer.shadowPath = CGPath.init(rect: CGRect.init(x: 0, y: 0, width: 50, height: 50), transform: nil)
self.layer.shadowOpacity = 1.0;
self.layer.shadowOffset = CGSize(width: 1, height: 1)
Newsonic
  • 413
  • 4
  • 19
  • what if you don't know frame at the time of this initialization? @Demosthese above wrote absolutely correct example with layout sibviews – iago849 Jun 21 '21 at 08:37