NSWindow 透明背景 NSCollectionView 背景不重绘

NSWindow Transparent Background NSCollectionView background not repainting

我正在尝试创建一个半透明的 macOS 应用程序。就像 macOS 附带的终端应用程序一样。我在 Storyboard 中创建了一个透明的 NSWindow 子类和一个非常标准的 NSCollectionView。我可以让应用程序成为半透明的,但是当我滚动 NSCollectionViewItems 时,它会使背景完全透明。

问题代码在Github

问题示例

我尝试了很多东西

这里是习俗UIWindow

import Cocoa

class MainWindow: NSWindow {

    override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) {
        super.init(contentRect: contentRect, styleMask: style, backing: backingStoreType, defer: false)
        self.backingType = NSWindow.BackingStoreType.buffered
        self.alphaValue = 1.0
        self.backgroundColor = NSColor.clear
        self.isOpaque = false
    }
}

这里是ViewController

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var collectionView: NSCollectionView!
    @IBOutlet weak var scrollView: NSScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()

        configureCollectionView()
        collectionView.register(ReceiverCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "Cell"))
    }

    private func configureCollectionView() {
        let flowLayout = NSCollectionViewFlowLayout()
        flowLayout.itemSize = NSSize(width: 100.0, height: 100.0)
        flowLayout.sectionInset = NSEdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)
        flowLayout.minimumInteritemSpacing = 20.0
        flowLayout.minimumLineSpacing = 20.0
        collectionView.collectionViewLayout = flowLayout

        scrollView.drawsBackground = false
        scrollView.contentView.drawsBackground = false
        scrollView.backgroundColor = NSColor(calibratedRed: 0.0, green: 0.0, blue: 0.0, alpha: 0.1)

        collectionView.backgroundColors = [NSColor(calibratedRed: 0.0, green: 0.0, blue: 0.0, alpha: 0.1)]
    }
}

extension ViewController: NSCollectionViewDataSource {
    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
        let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "Cell"), for: indexPath) 
        return item
    }
}

经过反复试验(更多错误)我找到了解决方案。

在 NSWindow 子类中,如果您设置背景颜色,这将消除背景中的清晰 "holes"。

import Cocoa

class MainWindow: NSWindow {

    override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) {
        super.init(contentRect: contentRect, styleMask: style, backing: backingStoreType, defer: false)
        self.backingType = NSWindow.BackingStoreType.buffered
        self.alphaValue = 1.0
        self.backgroundColor = NSColor(calibratedRed: 0.0, green: 0.0, blue: 0.0, alpha: 0.2)
        self.isOpaque = false
    }
}

ViewController还需要一些东西

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var collectionView: NSCollectionView!
    @IBOutlet weak var scrollView: NSScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()

        configureCollectionView()
        collectionView.register(ReceiverCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "Cell"))
    }

    private func configureCollectionView() {
        let flowLayout = NSCollectionViewFlowLayout()
        flowLayout.itemSize = NSSize(width: 100.0, height: 100.0)
        flowLayout.sectionInset = NSEdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)
        flowLayout.minimumInteritemSpacing = 20.0
        flowLayout.minimumLineSpacing = 20.0
        collectionView.collectionViewLayout = flowLayout

        scrollView.drawsBackground = false
        scrollView.contentView.drawsBackground = false
        scrollView.backgroundColor = NSColor.clear

        collectionView.backgroundColors = [.clear]
    }
}

extension ViewController: NSCollectionViewDataSource {
    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
        let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "Cell"), for: indexPath) 
        return item
    }
}