设置自定义 NSView 的 backgroundColor

Setting backgroundColor of custom NSView

osx使用故事板绘制到 NSView 的过程是怎样的?我在 NSViewController 中添加了一个 NSView。然后,我添加了一些约束和一个出口。

接下来,我添加了一些代码来更改颜色: 导入 Cocoa

class ViewController: NSViewController {

    @IBOutlet var box: NSView!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear() {
        box.layer?.backgroundColor = NSColor.blueColor().CGColor
        //box.layer?.setNeedsDisplay()
    }

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

我想自定义绘图并更改 NSView 的颜色。我有 过去在 iOS 上进行过复杂的绘图,但我完全被困在这里。 有人看到我做错了什么吗?

这个效果好多了:

    override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)
        NSColor.blueColor().setFill()
        NSRectFill(dirtyRect);
    }

正确的做法是

class ViewController: NSViewController {

@IBOutlet var box: NSView!

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.wantsLayer = true

}

override func viewWillAppear() {
    box.layer?.backgroundColor = NSColor.blue.cgColor
    //box.layer?.setNeedsDisplay()
}

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

edit/update:

另一种选择是设计您自己的彩色视图:

import Cocoa
@IBDesignable class ColoredView: NSView {
    @IBInspectable var backgroundColor: NSColor = .clear
    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
        backgroundColor.set()
        dirtyRect.fill()
    }
}

然后你只需要添加一个自定义视图 NSView 并在检查器中设置自定义 class:


原答案

Swift 3.0 或更高版本

extension NSView {
    var backgroundColor: NSColor? {
        get {
            guard let color = layer?.backgroundColor else { return nil }
            return NSColor(cgColor: color)
        }
        set {
            wantsLayer = true
            layer?.backgroundColor = newValue?.cgColor
        }
    }
}

let myView = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
myView.backgroundColor = .red

Swift 通过 属性

extension NSView {

    var backgroundColor: NSColor? {
        get {
            if let colorRef = self.layer?.backgroundColor {
                return NSColor(CGColor: colorRef)
            } else {
                return nil
            }
        }
        set {
            self.wantsLayer = true
            self.layer?.backgroundColor = newValue?.CGColor
        }
    }   
}

用法:

    yourView.backgroundColor = NSColor.greenColor()

其中 yourViewNSView 或其任何子类

更新 Swift 3

extension NSView {

    var backgroundColor: NSColor? {

        get {
            if let colorRef = self.layer?.backgroundColor {
                return NSColor(cgColor: colorRef)
            } else {
                return nil
            }
        }

        set {
            self.wantsLayer = true
            self.layer?.backgroundColor = newValue?.cgColor
        }
    }
}

@CryingHippo 更新到 Swift 3 解决方案(在我的例子中,它显示的颜色不是每个 运行)。我添加了 DispatchQueue.main.async,现在它会在应用程序的每个 运行 上显示颜色。

extension NSView {

    var backgroundColor: NSColor? {

        get {
            if let colorRef = self.layer?.backgroundColor {
                return NSColor(cgColor: colorRef)
            } else {
                return nil
            }
        }

        set {

            DispatchQueue.main.async { 

                self.wantsLayer = true
                self.layer?.backgroundColor = newValue?.cgColor

            }

        }
    }
}

从 macOS 10.13 (High Sierra) 开始,NSView 会响应选择器 backgroundColor,尽管没有记录!

在支持 暗模式MacOS 10.14 中设置 NSView 背景颜色的最佳方法:

1/ 在 Assets.xcassets 中创建你的颜色

2/ 将 NSView 子类化并添加:

class myView: NSView {
    override func updateLayer() {
       self.layer?.backgroundColor = NSColor(named: "customControlColor")?.cgColor
    }
}

非常简单和深色模式支持您选择的颜色!

完整指南:https://developer.apple.com/documentation/appkit/supporting_dark_mode_in_your_interface

None 的解决方案是使用 Cocoa 框架的纯粹力量。 正确的解决方案是使用 NSBox 而不是 NSView。一直支持fillColorborderColor

  1. titlePosition设置为None
  2. boxType设置为Custom
  3. borderType设置为None
  4. 从资产目录中设置您想要的fillColor(深色模式很重要)
  5. borderWidthborderRadius设置为0

奖金:

  • 它对外观的突然变化(从亮到暗)做出动态反应
  • 它支持动画(不需要 dynamic + 不需要 override animation(forKey key:NSAnimatablePropertyKey) ->
  • 未来自动支持 macOS

警告:

  • 在深色模式下使用 NSBox + 系统颜色将正确应用着色。如果您不想着色,请使用目录颜色。

替代方案是提供 NSView 的子类并在 updateLayer

中进行绘图更新
import Cocoa

@IBDesignable
class CustomView: NSView {

    @IBInspectable var backgroundColor : NSColor? {
        didSet { needsDisplay = true }
    }
    override var wantsUpdateLayer: Bool {
        return true
    }

    override func updateLayer() {
        guard let layer = layer else { return }
        layer.backgroundColor = backgroundColor?.cgColor
    }
}

调色:

只需一行代码就足以改变任何NSView对象的背景:

myView.setValue(NSColor.blue, forKey: "backgroundColor")

除此之外,您还可以在具有 keyPath backgroundColorColor 类型的界面设计器中添加用户定义的属性。