NSProgressIndicator 无法将背景颜色设置为白色

Posted

技术标签:

【中文标题】NSProgressIndicator 无法将背景颜色设置为白色【英文标题】:NSProgressIndicator can't set background color to white 【发布时间】:2016-04-28 21:26:54 【问题描述】:

当我将进度指示器的背景设置为绿色时,它会按预期工作。

代码

loadingIndicator.wantsLayer = true
loadingIndicator.layer?.backgroundColor = NSColor.greenColor().CGColor

结果

但是当我将背景颜色设置为白色时,背景颜色保持灰色(而不是变为白色)。

代码

loadingIndicator.wantsLayer = true
loadingIndicator.layer?.backgroundColor = NSColor.whiteColor().CGColor

结果

为什么将背景颜色设置为白色不起作用,而将绿色设置为?我该如何纠正这个问题?我在 OS X 10.11.4 上。

编辑:这显然只发生在进度指示器位于显示为弹出框的视图内时。

【问题讨论】:

对此的任何解决方案,弹出窗口中的指示器存在相同问题 【参考方案1】:

我在 NSPopover 中使用 NSProgressIndicator 时遇到了同样的问题。

我的解决方案是将外观设置为弹出框,如下所示。

popover.appearance = NSAppearance(named: NSAppearanceNameAqua)
在 OSX 10.11.5 / Xcode7.3.1 上试过 除了 NSAppearanceNameVibrantDark 之外的任何其他名称也可以使用

我不确定为什么会发生这种情况,但是在设置属性后我得到了正确的白色背景颜色。

Screenshot: white background progress inside popover

【讨论】:

【参考方案2】:

我找到了解决此问题的方法。 NSProgressIndicator 的 CALayer 有一个子层,显示您所看到的着色背景颜色。隐藏该子图层将导致不显示任何背景,并保持微调器可见。

CALayer *layer = [[self popoverProgressIndicator] layer];
CALayer *backgroundLayer = [[layer sublayers] firstObject];
[backgroundLayer setHidden:YES];

我只在使用解决方案 here 更改背景的 NSPopover 中看到此问题。

【讨论】:

这适用于我在 macOS Catalina 上,但仅在显示 NSProgressIndicator 之后。即使viewDidAppear 对我来说也太早了。【参考方案3】:

我最近也遇到过这个问题,但我的问题与 macOS 10.14 中的深色模式/浅色模式有关。正如其他人所提到的,在 NSPopover 中使用 NSProgressIndicator 时似乎会发生这种情况,但在 Safari App Extension 弹出框内也是如此(我认为这是因为 Safari 弹出框也是您无法直接访问的 NSPopover)。正如horimislime 提到的,摆弄外观似乎可以解决问题。

我创建了一个 NSProgressIndicator 子类,只有当应用程序在 macOS 10.14 或更高版本中运行时,它才会自动将其自己的外观设置为系统拥有的外观,即使在应用程序运行时它发生了变化。进度指示器在以前的操作系统版本中适用于我,因此如果系统低于 10.14,我将保持不变。

代码如下:

import Cocoa

class TransparentProgressIndicator: NSProgressIndicator 

    override func awakeFromNib() 
        super.awakeFromNib()

        if #available(OSX 10.14, *) 
            // register an observer to detect when the system appearance changes
            UserDefaults.standard.addObserver(self, forKeyPath: "AppleInterfaceStyle", options: .new, context: nil)

            // set the starting appearance to the one the system has
            let light = NSAppearance(named: .aqua)
            let dark = NSAppearance(named: .darkAqua)
            self.appearance = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") == "Dark" ? dark : light
        
    

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 

        if #available(OSX 10.14, *) 
            if keyPath == "AppleInterfaceStyle" 

                // set the current appearance to the one the system has
                let val: String? = change?[NSKeyValueChangeKey.newKey] as? String

                if (val == "Dark") 
                    self.appearance = NSAppearance(named: .darkAqua)
                
                else 
                    self.appearance = NSAppearance(named: .aqua)
                
            
        
    

    deinit 
        if #available(OSX 10.14, *) 
            UserDefaults.standard.removeObserver(self, forKeyPath: "AppleInterfaceStyle")
        
    


这样,进度指示器保持透明,没有奇怪的着色背景,并且仍然根据系统外观更改其配色方案。 为了使用它,您需要将此子类的名称添加为界面构建器中的“自定义类”属性:

现在,为了获得问题中要求的自定义背景颜色,您可以只拥有一个包含 NSBox 并为其添加颜色:

【讨论】:

【参考方案4】:

当我在 NSPopover 中使用 NSProgressIndicator 时遇到了同样的问题。

我的解决方案是将外观设置为NSProgressIndicator,如下所示。

@IBOutlet weak var progressIndicator: NSProgressIndicator!

override func viewDidLoad() 
    super.viewDidLoad()
    self.progressIndicator.appearance = NSAppearance(named: .aqua)

如果您愿意,即使将外观设置为整个弹出框也可以解决问题:

popover.appearance = NSAppearance(named: .aqua)

【讨论】:

以上是关于NSProgressIndicator 无法将背景颜色设置为白色的主要内容,如果未能解决你的问题,请参考以下文章

无法从 appdelegate.m 为 NSProgressIndicator 设置动画

NSProgressIndicator 的 setControlTint 没有效果

OS X 停靠图标中的 NSProgressIndicator 显示为灰色,如何制作标准蓝色

子类 NSProgressIndicator

斯威夫特:如何使用 NSProgressIndicator?

如何检查 NSProgressIndicator 当前是不是为动画?