首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何改变NSSwitch的色调?

如何改变NSSwitch的色调?
EN

Stack Overflow用户
提问于 2020-01-04 18:59:37
回答 2查看 630关注 0票数 0

NSSwitch现在看起来相当苍白:

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

但IB上没有色调部分,就像在iOS上一样。

所以我在代码中试试我的运气:

代码语言:javascript
复制
@IBOutlet weak var alwaysConnectedSwitch: NSSwitch!

override func viewWillAppear() {
    super.viewWillAppear()
    self.alwaysConnectedSwitch.layer?.backgroundColor = CGColor.init(gray: 1, alpha: 1)
}

但是self.alwaysConnectedSwitch.layer似乎为零,所以没有设置任何内容。

EN

回答 2

Stack Overflow用户

发布于 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应该如何绘制到层中。下面是最后面视图的示例字典:

代码语言:javascript
复制
{
    kCUIPresentationStateKey = kCUIPresentationStateInactive;
    kCUIScaleKey = 2;
    kCUIUserInterfaceLayoutDirectionKey = kCUIUserInterfaceLayoutDirectionLeftToRight;
    size = regular;
    state = normal;
    value = 0;
    widget = kCUIWidgetSwitchFill;
}

不幸的是,这意味着样式主要是由widget = kCUIWidgetSwitchFill;看到的预定义字符串决定的,它涉及到如何根据系统颜色(暗/亮)或高亮颜色绘制填充颜色或禁用颜色。颜色与NSAppearance绑定在一起,没有一种明确的方法可以覆盖这些颜色。

一种(不推荐的,千万不要这么做)的解决方案是去掉NSWidgetView的updateLayer调用,在你想要的情况下做你自己的额外的层定制。使用Swift编写的示例:

代码语言:javascript
复制
/// 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,这样你就会更安全。

票数 2
EN

Stack Overflow用户

发布于 2020-04-18 15:45:42

我不知道你到底面临着什么样的问题,但这对我很有效:

代码语言:javascript
复制
override func viewDidLoad() {
    super.viewDidLoad()


    zzz.layer!.backgroundColor = NSColor.systemRed.cgColor
    zzz.layer!.masksToBounds = true
    zzz.layer!.cornerRadius = 10

这是yelds

您可能希望播放/调整其他边框设置,如borderWidth或borderColor

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59590042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档