【问题标题】:NSColor systemColor not changing when dark/light mode switchedNSColor systemColor 在暗/亮模式切换时不会改变
【发布时间】:2019-11-19 22:56:42
【问题描述】:

我正在尝试通过在NSViewController 中切换暗/亮模式来更改图像的颜色。 我正在使用此代码来更改图像的颜色:

- (NSImage *)image:(NSImage *)image withColour:(NSColor *)colour
{   
    NSImage *img = image.copy;
    [img lockFocus];
    [colour set];
    NSRect imageRect = NSMakeRect(0, 0, img.size.width, img.size.height);
    NSRectFillUsingOperation(imageRect, NSCompositingOperationSourceAtop);
    [img unlockFocus];
    return img;
}

我试过从viewWillLayout调用这个方法

self.help1Image.image = [self image:self.help1Image.image withColour:[NSColor systemRedColor]];

但系统颜色似乎总是返回相同的 RGB 值。

我也尝试过收听通知AppleInterfaceThemeChangedNotification,但即使在这里,RGB 值似乎也保持不变1.000000 0.231373 0.188235

[[NSDistributedNotificationCenter defaultCenter] addObserverForName:@"AppleInterfaceThemeChangedNotification"
                                                             object:nil
                                                              queue:nil
                                                         usingBlock:^(NSNotification * _Nonnull note) {

                                                             NSLog(@"AppleInterfaceThemeChangedNotification");
                                                             self.help1Image.image = [self image:self.help1Image.image withColour:[NSColor systemRedColor]];

                                                             NSColorSpace *colorSpace = [NSColorSpace sRGBColorSpace];
                                                             NSColor *testColor = [[NSColor systemBlueColor] colorUsingColorSpace:colorSpace];
                                                             CGFloat red = [testColor redComponent];
                                                             CGFloat green = [testColor greenComponent];
                                                             CGFloat blue = [testColor blueComponent];
                                                             NSLog(@"%f %f %f", red, green, blue);
                                                         }];

我在 NSButtonCell sublass 和覆盖 layout 中工作正常,但无法在 NSViewController 中工作

【问题讨论】:

    标签: macos nscolor macos-darkmode


    【解决方案1】:

    首先,查看文档部分“使用特定方法更新自定义视图”here。它说:

    当用户改变系统外观时,系统会自动要求每个窗口和视图重新绘制自己。在此过程中,系统会调用下表中列出的适用于 macOS 和 iOS 的几种众所周知的方法来更新您的内容。系统会在调用这些方法之前更新 trait 环境,因此如果您在其中进行所有外观敏感的更改,您的应用会正确更新自身。

    但是,该表中没有列出 NSViewController 方法。

    由于视图的外观可以独立于当前或“系统”外观,因此在视图控制器中对外观变化做出反应的最佳方法是 KVO 视图的 effectiveAppearance 属性,或者在 [NSView viewDidChangeEffectiveAppearance] 中执行某些操作.

    - (void)viewDidLoad 
    {
        [self addObserver:self forKeyPath:@"view.effectiveAppearance" options:0 context:nil];
    }
    
    // ...
    
    - (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
    {
        if ([keyPath isEqualToString:@"view.effectiveAppearance"])
        {
    // ...
    
    

    NSAppearance 有一个currentAppearance 属性,它独立于系统外观,并由 Cocoa 在上面列出的方法中更新。在其他任何地方,您都需要自己检查是否正确。同样,惯用的方式是通过视图的effectiveAppearance

    [NSAppearance setCurrentAppearance:someView.effectiveAppearance];
    

    所以,在你的情况下,以下对我很有效:

    - (void)viewDidLoad 
    {
        [super viewDidLoad];
    
        [self addObserver:self forKeyPath:@"view.effectiveAppearance" options:0 context:nil];
    }
    
    -(void)viewDidLayout
    {
        self.help1Image.image = [self image:self.help1Image.image withColour:[NSColor systemRedColor]];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        if ([keyPath isEqualToString:@"view.effectiveAppearance"])
        {
                    [NSAppearance setCurrentAppearance:self.view.effectiveAppearance];
    
                    self.help1Image.image = [self image:self.help1Image.image withColour:[NSColor systemRedColor]];
        }
    }
    

    【讨论】:

    • 很好的答案,谢谢。这里的关键是[NSAppearance setCurrentAppearance:self.view.effectiveAppearance]; 我可以在我发布在我的问题中的通知中设置它,然后颜色是正确的。
    猜你喜欢
    • 2020-07-07
    • 2021-03-05
    • 2021-12-30
    • 2020-10-20
    • 2020-07-07
    • 2020-09-03
    • 2021-04-02
    • 2020-08-24
    • 2021-03-28
    相关资源
    最近更新 更多