NSSwitch现在看起来相当苍白:

我正试着在iOS上像这样改变色调:

但IB上没有色调部分,就像在iOS上一样。
所以我在代码中试试我的运气:
@IBOutlet weak var alwaysConnectedSwitch: NSSwitch!
override func viewWillAppear() {
super.viewWillAppear()
self.alwaysConnectedSwitch.layer?.backgroundColor = CGColor.init(gray: 1, alpha: 1)
}但是self.alwaysConnectedSwitch.layer似乎为零,所以没有设置任何内容。
发布于 2020-01-09 07:26:02
如果你确实需要改变样式,我会推荐一个第三方自定义控件,它可以让你根据需要自定义外观;一些可行的建议可以在here找到。从10.15开始,NSSwitch根本没有您想要的定制功能。如果你不关心细节,现在就停止阅读吧
也就是说,剖析NSSwitch的组件是很有趣的。与许多Cocoa控件不同的是,该控件没有支持NSCell。文档明确说明了这点:
NSSwitch不使用NSCell实例来提供其功能。cellClass类属性和单元格实例属性都返回nil,并且它们忽略设置非nil值的尝试。
因此,它是一个相当现代的控件,由绘制内容的层组成。有3个属于私有NSView子类的NSWidgetView。

这些视图主要利用-[NSView updateLayer]来根据通过-[NSWidgetView setWidgetDefinition:]提供的内容来绘制它们的后台CALayer期望值。此方法传入一个值字典,该字典定义NSWidgetView应该如何绘制到层中。下面是最后面视图的示例字典:
{
kCUIPresentationStateKey = kCUIPresentationStateInactive;
kCUIScaleKey = 2;
kCUIUserInterfaceLayoutDirectionKey = kCUIUserInterfaceLayoutDirectionLeftToRight;
size = regular;
state = normal;
value = 0;
widget = kCUIWidgetSwitchFill;
}不幸的是,这意味着样式主要是由widget = kCUIWidgetSwitchFill;看到的预定义字符串决定的,它涉及到如何根据系统颜色(暗/亮)或高亮颜色绘制填充颜色或禁用颜色。颜色与NSAppearance绑定在一起,没有一种明确的方法可以覆盖这些颜色。
一种(不推荐的,千万不要这么做)的解决方案是去掉NSWidgetView的updateLayer调用,在你想要的情况下做你自己的额外的层定制。使用Swift编写的示例:
/// Swizzle out NSWidgetView's updateLayer for our own implementation
class AppDelegate: NSObject, NSApplicationDelegate {
/// Swizzle out NSWidgetView's updateLayer for our own implementation
func applicationWillFinishLaunching(_ notification: Notification) {
let original = Selector("updateLayer")
let swizzle = Selector("xxx_updateLayer")
if let widgetClass = NSClassFromString("NSWidgetView"),
let originalMethod = class_getInstanceMethod(widgetClass, original),
let swizzleMethod = class_getInstanceMethod(NSView.self, swizzle) {
method_exchangeImplementations(originalMethod, swizzleMethod)
}
}
}
extension NSView {
@objc func xxx_updateLayer() {
// This calls the original implementation so all other NSWidgetViews will have the right look
self.xxx_updateLayer()
guard let dictionary = self.value(forKey: "widgetDefinition") as? [String: Any],
let widget = dictionary["widget"] as? String,
let value = (dictionary["value"] as? NSNumber)?.intValue else {
return
}
// If we're specifically dealing with this case, change the colors and remove the contents which are set in the enabled switch case
if widget == "kCUIWidgetSwitchFill" {
layer?.contents = nil;
if value == 0 {
layer?.backgroundColor = NSColor.red.cgColor;
} else {
layer?.backgroundColor = NSColor.yellow.cgColor;
}
}
}
}再说一次,不要这样做!你将来一定会崩溃,苹果会在App Store中拒绝这一点,而且你有了一个自定义控件,它可以做你想做的事情,而不需要弄乱私有API,这样你就会更安全。
发布于 2020-04-18 15:45:42
我不知道你到底面临着什么样的问题,但这对我很有效:

override func viewDidLoad() {
super.viewDidLoad()
zzz.layer!.backgroundColor = NSColor.systemRed.cgColor
zzz.layer!.masksToBounds = true
zzz.layer!.cornerRadius = 10这是yelds

您可能希望播放/调整其他边框设置,如borderWidth或borderColor
https://stackoverflow.com/questions/59590042
复制相似问题