linus_hologram
linus_hologram

Reputation: 1715

NSVisualEffectView not applying intended "frosting" effect

Modern applications increasingly often use the typical "frosting" effect for their window backgrounds. Such an effect usually consists of a combination of blurring and playing with the vibrancy of the background. To my knowledge, and according to Apple's Documentation, this is done using a NSVisualEffectView.

I am trying to follow an example from this GitHub repo (specifically: Example 6.). Below code shows my NSPanel implementation using the NSVisualEffectView which doesn't seem to have any effect on the appearance of my panel.

public class MyCustomPanel: NSPanel {

    public init() {
        super.init(contentRect: NSRect(origin: NSPoint(x: 200, y: 200), size: .zero), styleMask: [.fullSizeContentView, .nonactivatingPanel], backing: .buffered, defer: false)

        self.isFloatingPanel = true
        self.level = .floating
        self.worksWhenModal = true
        self.hidesOnDeactivate = false
        self.titleVisibility = .hidden
        self.backgroundColor = .clear
        self.isMovableByWindowBackground = true
        self.titlebarAppearsTransparent = true
        self.animationBehavior = .utilityWindow

        self.contentView = NSHostingView(rootView: MyCustomSwiftUIView())

        self.isOpaque = true
        self.backgroundColor = .gray
    
        let visualEffect = NSVisualEffectView() // doesn't seem to have any effect
        visualEffect.translatesAutoresizingMaskIntoConstraints = false
        visualEffect.material = .windowBackground
        visualEffect.blendingMode = .behindWindow
        visualEffect.state = .active
        visualEffect.wantsLayer = true
        visualEffect.layer?.cornerRadius = 16.0

        self.titleVisibility = .hidden
        self.styleMask.remove(.titled)
        self.isMovableByWindowBackground = true
        self.contentView?.addSubview(visualEffect)

        guard let constraints = self.contentView else {
            return
        }

        visualEffect.leadingAnchor.constraint(equalTo: constraints.leadingAnchor).isActive = true
        visualEffect.trailingAnchor.constraint(equalTo: constraints.trailingAnchor).isActive = true
        visualEffect.topAnchor.constraint(equalTo: constraints.topAnchor).isActive = true
        visualEffect.bottomAnchor.constraint(equalTo: constraints.bottomAnchor).isActive = true
    }
}

This results in the following panel appearance:

enter image description here

As you can see, no frosting appearance or corner radius is applied to the panel's content view.

Why is that? And how can I resolve this so my panel applies the proper frosting effect?

Upvotes: 1

Views: 276

Answers (1)

MrO
MrO

Reputation: 725

I've seen that sort of behavior when using a view which doesn't draw a "clear" color in its own drawRect(_:), as a window's content view. You get the chunky black box of the window's bitmap backing store.

So, first thing I'd try - create a new ContentView class that draws clear using its drawRect(_:) method. Add the NSVisualEffectView as a subview of this view instead. See where that goes and report back.

Upvotes: 0

Related Questions