【问题标题】:Setting backgroundColor of custom NSView设置自定义 NSView 的 backgroundColor
【发布时间】:2015-03-09 12:29:02
【问题描述】:

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

接下来,我添加了一些代码来改变颜色: 进口可可

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 上进行过复杂的绘图,但我完全被困在这里。 有谁知道我做错了什么?

【问题讨论】:

    标签: swift macos cocoa nsview xcode-storyboard


    【解决方案1】:

    正确的做法是

    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.
        }
    }}
    

    【讨论】:

    【解决方案2】:

    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
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      编辑/更新:

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

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

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


      原答案

      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
      

      【讨论】:

      • 这太棒了。我不敢相信我没有想到这一点。有了这个简单的扩展,Cocoa 中的视图背景现在就像在 Cocoa Touch 中一样简单。 :)
      • 我唯一要注意的是覆盖现有的backgroundColor 实现,例如在文本视图上
      • 在启动时,此解决方案有效并设置了自定义背景颜色。但是颜色并没有应用于界面构建器中的视图,就像在屏幕截图(macos 10.15.6)中一样,所以糟糕的预览对我来说有点杀了它。
      • @Starwave 无法重现您的问题。当我使用界面生成器 10.15.5 更改颜色时,它对我有用。我正在使用 NSView 子类方法 ColoredView。您确定有背景用户定义的属性键路径颜色集吗? dropbox.com/s/dzgr9ickj0tbn51/…
      • 好吧,你是对的,它确实有效。打开 IB,整个项目突然开始完全重建,在背景选择上方现在显示“Designables: Up to date”。意味着这是一些奇怪的 IB 缓存错误。
      【解决方案4】:

      这样效果更好:

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

      【讨论】:

      • 定义:“更好”。那又如何? drawRect 具有 NSVIew 扩展没有的性能影响。
      【解决方案5】:

      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

      【讨论】:

      • 我认为这是最好的方法
      • 确实,由于暗模式,这是当今正确的方法。除非您的目标颜色对于 Light 和 Dark 模式都可接受,否则如果用户在显示视图时更改其 Light vs. Dark System Preference,则较早接受的答案将不会更新背景颜色。这个答案会。
      • 而且,如果您想要适当的浅灰色或深灰色,则无需创建资产。使用“变色龙”NSColor 对象之一,该对象会自动切换为 Light 与 Dark 模式,例如 NSColor.controlBackgroundColor
      【解决方案6】:

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

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

      除此之外,您还可以在类型为Color 的界面设计器中添加一个用户定义的属性,其键路径为backgroundColor

      【讨论】:

      • 我尝试了所有方法,这是唯一适合我的方法
      【解决方案7】:

      @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
      
                  }
      
              }
          }
      }
      

      【讨论】:

        【解决方案8】:

        没有一个解决方案是使用 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
            }
        }
        

        着色:

        【讨论】:

          【解决方案9】:

          由于 macOS 10.13 (High Sierra) NSView 响应选择器背景颜色,尽管它没有记录!

          【讨论】:

            猜你喜欢
            • 2022-08-18
            • 1970-01-01
            • 2013-06-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多