How to display shadow for NSView?
Asked Answered
B

3

13

I have gone through many threads here and other blogs but not able to solve this issue. I have a added a subview in content view of window. Here is the storyboard--

enter image description here-

I have dragged out outlet of customView to view controller and here is the code for view controller -

import Cocoa
import QuartzCore

class ViewController: NSViewController {

    @IBOutlet weak var customView: NSView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.view.wantsLayer = true
        self.customView.wantsLayer = true
        self.customView.layer?.backgroundColor = NSColor.redColor().CGColor
        self.customView.layer?.cornerRadius = 5.0
        self.customView.layer?.shadowOpacity = 1.0
        self.customView.layer?.shadowColor = NSColor.blackColor().CGColor
        self.customView.layer?.shadowOffset = NSMakeSize(0, -3)
        self.customView.layer?.shadowRadius = 20
    }

    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }
}

I have added QuartzCore frame work in my project - enter image description here

But the shadow is not appearing, here is the screen shot - enter image description here.

I am not able to solve what appears to be trivial. What am I missing? thanks for your help.

Bertha answered 30/9, 2015 at 6:51 Comment(2)
Probably you need to make the superview layer-backed, too.Finley
I have added self.view.wantsLayer = true for the content view of window. And the red colour view is subview of content view itself.Bertha
B
39

If I add the following line it solves the problem-

self.customView.shadow = NSShadow()

Final code is -

import Cocoa
import QuartzCore

class ViewController: NSViewController {

    @IBOutlet weak var customView: NSView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.view.wantsLayer = true
        self.view.superview?.wantsLayer = true
        self.customView.wantsLayer = true
        self.customView.shadow = NSShadow()
        self.customView.layer?.backgroundColor = NSColor.redColor().CGColor
        self.customView.layer?.cornerRadius = 5.0
        self.customView.layer?.shadowOpacity = 1.0
        self.customView.layer?.shadowColor = NSColor.greenColor().CGColor
        self.customView.layer?.shadowOffset = NSMakeSize(0, 0)
        self.customView.layer?.shadowRadius = 20
    }

    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }


}

I am not able to identify the issue may be someone here will point it out.

Bertha answered 1/10, 2015 at 8:22 Comment(4)
The NSShadow() is the key. Next the hosting view (e.g. superview) needs wantsLayer to true.Catercornered
In the Core Animation Programming guide, it says some layer properties should not be directly modified for layer backed view in OS X. In this list of properties are shadowOffset, shadowColor, shadowRadius, shadowOpacity. developer.apple.com/library/content/documentation/Cocoa/… So it is better to create a shadow object, set the properties on this object and then assign it to the layer's shadow.Sharecrop
in my case the NSShadow invalidates the layer cornerRadiusCopyholder
This helped me! I just had to set wantsLayer to truePruitt
F
0

I added code like below to get shadow to NSView. It worked For me.

     @IBOutlet weak var leftCustomBgView: NSView!
    
     override func viewDidAppear() {
        super.viewDidAppear()
        initialSetUp()
     }

    fileprivate func initialSetUp() {
        self.leftCustomBgView.wantsLayer = true
        self.leftCustomBgView.shadow = NSShadow()
        self.leftCustomBgView.layer?.backgroundColor = NSColor.white.cgColor
        self.leftCustomBgView.layer?.cornerRadius = 6
        self.leftCustomBgView.layer?.shadowColor = NSColor.black.cgColor
        self.leftCustomBgView.layer?.shadowOpacity = 1.0
        self.leftCustomBgView.layer?.shadowOffset = CGSize(width: 0, height: 0)
        self.leftCustomBgView.layer?.shadowRadius = 6
    }

--------------- OR -----------------

self.leftCustomBgView.addShadow(customViewBgColor: NSColor.white,
                                    customViewRadius: 6,
                                    shadowViewColor: NSColor.black,
                                    shadowViewRadius: 6,
                                    opacity: 1.0)

extension NSView {
//Add Shadow to NSView
func addShadow(customViewBgColor: NSColor, customViewRadius: CGFloat, shadowViewColor: NSColor, shadowViewRadius: CGFloat, opacity: Float) {
    self.wantsLayer = true
    self.shadow = NSShadow()
    self.layer?.backgroundColor = customViewBgColor.cgColor
    self.layer?.cornerRadius = customViewRadius
    self.layer?.shadowColor = shadowViewColor.cgColor
    self.layer?.shadowOpacity = opacity
    self.layer?.shadowOffset = CGSize(width: 0, height: 0)
    self.layer?.shadowRadius = shadowViewRadius
 }
}
Frosty answered 21/12, 2022 at 4:27 Comment(0)
S
0

An alternative to the accepted answer, you can configure the NSShadow before assigning it.

The documentation says, as some folks have already pointed out:

If the view does not have a layer, setting the value of this property has no effect.

Example

let shadow = NSShadow()
shadow.shadowColor = .red
shadow.shadowBlurRadius = 20
        
let view = NSView()
view.wantsLayer = true
view.shadow = shadow
Sharpset answered 3/3, 2023 at 16:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.