代码之家  ›  专栏  ›  技术社区  ›  93sauu

如何在macOS 10.14上检测到暗模式?

  •  8
  • 93sauu  · 技术社区  · 7 年前

    在macOS 10.14中,用户可以选择采用全系统的浅色或深色外观,我需要根据当前模式手动调整一些颜色。

    3 回复  |  直到 6 年前
        1
  •  19
  •   DarkDust    6 年前

    因为你通常通过 effectiveAppearance 是一个复合的外观,直接问它的名字可能不是一个可靠的解决方案。

    要求 currentAppearance 通常也不是一个好主意,因为视图可能被显式地设置为light模式,或者您想知道视图在 drawRect: 在模式切换后可能会得到不正确的结果。

    我想出的解决方案是这样的:

    BOOL appearanceIsDark(NSAppearance * appearance)
    {
        if (@available(macOS 10.14, *)) {
            NSAppearanceName basicAppearance = [appearance bestMatchFromAppearancesWithNames:@[
                NSAppearanceNameAqua,
                NSAppearanceNameDarkAqua
            ]];
            return [basicAppearance isEqualToString:NSAppearanceNameDarkAqua];
        } else {
            return NO;
        }
    }
    

    你会喜欢用它 appearanceIsDark(someView.effectiveAppearance) 因为如果显式设置 someView.appearance .

    您还可以在 NSAppearance 并添加 - (BOOL)isDark 方法获取 someView.effectiveAppearance.isDark (最好选择一个苹果未来不太可能使用的名称,例如添加一个供应商前缀)。

        2
  •  16
  •   93sauu    7 年前

    我使用了当前的外观检查系统是否为10.14

    + (BOOL)isDarkMode {
        NSAppearance *appearance = NSAppearance.currentAppearance;
        if (@available(*, macOS 10.14)) {
            return appearance.name == NSAppearanceNameDarkAqua;
        }
    
        return NO;
    }
    

    要检测视图中模式的更改,方法如下:

    - (void)updateLayer;
    - (void)drawRect:(NSRect)dirtyRect;
    - (void)layout;
    - (void)updateConstraints;
    

    要检测视图控制器中模式的更改,方法如下:

    - (void)updateViewConstraints;
    - (void)viewWillLayout;
    - (void)viewDidLayout;
    

    使用通知:

    // Monitor menu/dock theme changes...
    [NSDistributedNotificationCenter.defaultCenter addObserver:self selector:@selector(themeChanged:) name:@"AppleInterfaceThemeChangedNotification" object: nil];
    
    -(void)themeChanged:(NSNotification *) notification {
        NSLog (@"%@", notification);
    }
    

    了解更多信息 Dark Mode Documentation

        3
  •  5
  •   Joey    6 年前

    斯威夫特4

    func isDarkMode(view: NSView?) -> Bool {
        if #available(OSX 10.14, *) {
            if let appearance = view?.effectiveAppearance ?? NSAppearance.current {
                return (appearance.name == .darkAqua)
            }
        }
        return false
    }
    

    更新:

    func isDarkMode(view: NSView) -> Bool {
        if #available(OSX 10.14, *) {
            return view.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
        }
        return false
    }
    
        4
  •  0
  •   Borzh brauliobo    6 年前

    要知道 应用程序 外观为深色,请使用下一个代码:

    + (BOOL)isDarkMode {
        NSString *interfaceStyle = [NSUserDefaults.standardUserDefaults valueForKey:@"AppleInterfaceStyle"];
        return [interfaceStyle isEqualToString:@"Dark"];
    }
    
        5
  •  0
  •   Panayotis    6 年前

    对我来说,这两个答案都不起作用,如果我想要一个全局状态,而不是每个视图,并且我没有访问该视图的权限,我希望收到更新通知。

    解决办法是 NSApp.effectiveAppearance 在主线程中,或者至少 之后 当前回调方法已返回到系统。

    所以,首先我必须按照Sal Moreno Abril的指示注册,代码如下

    [NSDistributedNotificationCenter.defaultCenter addObserver:self selector:@selector(themeChanged:) name:@"AppleInterfaceThemeChangedNotification" object: nil];
    

    然后在回调方法上写一些

    -(void)themeChanged:(NSNotification *) notification {
        [self performSelectorOnMainThread:@selector(themeChangedOnMainThread) withObject:nil waitUntilDone:false];
    }
    

    然后是实际代码:

    - (void) themeChangedOnMainThread {
        NSAppearance* appearance = NSApp.effectiveAppearance;
        NSString* name = appearance.name;
        BOOL dark = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]] == NSAppearanceNameDarkAqua;
    }
    

    波什的回答也有帮助,但似乎比其他人更脆弱。

        6
  •  0
  •   L.-T. Chen    6 年前

    实际上有8种可能 appearances 一个视图,其中4个是普通用途的。也就是说,

    1. NSAppearanceNameAqua 光模式,
    2. NSAppearanceNameDarkAqua 黑暗模式,
    3. NSAppearanceNameAccessibilityHighContrastAqua 增强对比度的灯光模式(从可访问性设置),
    4. NSAppearanceNameAccessibilityHighContrastDarkAqua 增加对比度的黑暗模式。

    直接比较

    appearance.name == NSAppearanceNameDarkAqua;

    如果对比度增加,可能无法检测到黑暗模式。所以,总是使用 bestMatchFromAppearancesWithNames 相反。

    为了更好的接近性,最好考虑到高对比度的外观。

    推荐文章