繁体   English   中英

NSStatusItem更改暗色调的图像

[英]NSStatusItem change image for dark tint

在OSX 10.10 beta 3中,Apple发布了他们的暗色调选项。 不幸的是,这也意味着几乎所有的状态栏图标(除了我见过的Apple和Path Finder),包括我的,都在黑暗的背景下保持黑暗。 如何在应用深色调时提供替代图像?

我没有看到NSStatusBarNSStatusItem上的API更改向我显示了一个更改,我假设它是一个通知或一些反应,以便在用户改变色调时轻松进行更改。

绘制图像的当前代码包含在NSView

- (void)drawRect:(NSRect)dirtyRect
{
    // set view background color
    if (self.isActive) {
        [[NSColor selectedMenuItemColor] setFill];
    } else {
        [[NSColor clearColor] setFill];
    }

    NSRectFill(dirtyRect);

    // set image
    NSImage *image = (self.isActive ? self.alternateImage : self.image);
    _imageView.image = image;
}

TL; DR:你不必在黑暗主题中做任何特别的事情。 为NSStatusItem(或NSStatusBarButton)提供模板图像,它将在任何菜单栏上下文中正确设置样式。


某些应用程序的状态项(例如PathFinder)已经在Dark Theme中工作的原因是因为他们没有在StatusItem上设置自己的自定义视图,而只是在StatusItem上设置模板图像。

就像是:

_statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
NSImage *image = [NSImage imageNamed:@"statusItemIcon"];
[image setTemplate:YES];
[_statusItem setImage:image];

这与您在Mavericks及其早期以及Yosemite以及任何未来版本中的预期完全一样, 因为它允许AppKit根据状态项状态执行图像的所有样式。

小牛

在小牛队(以及之前),只有2种独特的项目风格。 没有压力和压力。 这两种风格分别看起来纯粹是黑色和纯白色。 (实际上“纯黑色”并不完全正确 - 有一个小的效果,使它们看起来有点插入)。

因为只有两种可能的状态,状态栏应用程序可以设置自己的视图,只需根据突出显示的状态绘制黑色或白色即可轻松获得相同的外观。 (但再次注意,它不是纯粹的黑色,因此应用程序要么必须在图像中构建效果,要么满足于难以察觉的不合适的位置图标)。

优胜美地

在优胜美地,至少有32种独特的物品造型。 黑暗主题中没有压缩只是其中之一。 没有实用(或不实用)的方式让应用程序能够自己设置项目样式并使其在所有上下文中看起来都正确。

以下是六种可能的样式的示例:

六种可能的状态项目样式

非活动菜单栏上的状态项目现在具有特定样式,而不像过去那样简单的不透明度变化。 残疾人外表是另一种可能的变化; 这种可能性矩阵还有其他额外的维度

API

设置为NSStatusItem view属性的任意视图无法捕获所有这些变体,因此它(以及其他相关API)在10.10中已弃用。

但是,种子3在NSStatusItem上引入了新的API:

@property (readonly, strong) NSStatusBarButton *button NS_AVAILABLE_MAC(10_10);

这篇API有一些目的:

  1. 现在,应用程序可以获取状态项的屏幕位置(或显示弹出窗口),而无需设置自己的自定义视图。
  2. sendActionOn:上删除了对imagetitlesendActionOn:等API的需求。
  3. 为新API提供一个类:ie looksDisabled 这允许应用程序获得标准的禁用/关闭样式(如关闭时的蓝牙/时间机器),而无需自定义图像。

如果使用当前(非自定义视图)API无法完成某些操作,请为其提交增强请求。 StatusItems应该以在所有状态项中标准化的方式提供行为或外观。


更多讨论请访问https://devforums.apple.com/thread/234839 ,尽管我在这里总结了大部分内容。

我最终做了类似跟随我的自定义拖放NSStatusItemView :(使用Swift)

var isDark = false

func isDarkMode() {
    isDark = NSAppearance.currentAppearance().name.hasPrefix("NSAppearanceNameVibrantDark")
}

override func drawRect(dirtyRect: NSRect) {
    super.drawRect(dirtyRect)
    isDarkMode()
    // Now use "isDark" to determine the drawing colour.
    if isDark {
        // ...
    } else {
        // ...
    }
}

当用户在系统偏好设置中更改主题时,系统将调用NSView进行重新绘制,您可以相应地更改图标颜色。

如果您希望在此视图外调整其他自定义UI,则可以使用KVO观察视图的isDark键,也可以自行执行。

我创建了一个围绕NSStatusItem的基本包装器,您可以使用它在状态栏中为自定义视图提供10.10及更早版本的支持。 您可以在此处找到它: https//github.com/noahsmartin/YosemiteMenuBar基本思想是将自定义视图绘制到NSImage中,并将此图像用作状态栏项的模板图像。 此包装器还将单击事件转发到自定义视图,以便可以按照与10.10之前相同的方式处理它们。 该项目包含YosemiteMenuBar如何与状态栏上的自定义视图一起使用的基本示例。

当你的应用程序绘制了任何GUI元素时,你可以通过[NSAppearance currentAppearance]获得它的外观,它本身有一个name属性,它包含类似的内容

NSAppearanceNameVibrantDark->NSAppearanceNameAqua->NSAppearanceNameAquaMavericks

第一部分是外观的名称,也可以在NSAppearanceNameVibrantDarkNSAppearanceNameVibrantLight作为常量NSAppearanceNameVibrantLight

我不知道是否有办法获得第一部分,但我认为这就是现在的诀窍。

示例代码:

-(void)awakeFromNib {
    NSStatusItem* myStatusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    myStatusItem.title = @"Hello World";

    if ([[[NSAppearance currentAppearance] name] containsString:NSAppearanceNameVibrantDark]) {
        myStatusItem.title = @"Dark Interface";
    } else {
        myStatusItem.title = @"Light Interface";
    }
}

但是,如果你确实希望监控状态变化,你可以。 我也知道有一种比上面说的更好的方法来确定lite / dark模式,但我现在能记住它。

// Monitor menu/dock theme changes...
[[NSDistributedNotificationCenter defaultCenter] addObserver: self selector: @selector(themeChange:) name:@"AppleInterfaceThemeChangedNotification" object: NULL];

//
-(void) themeChange :(NSNotification *) notification
{
    NSLog (@"%@", notification);
}

最新的swift代码集图像模板方法在这里:

// Insert code here to initialize your application
if let button = statusItem.button {
    button.image = NSImage(named: "StatusIcon")
    button.image?.isTemplate = true  // Just add this line
    button.action = #selector(togglePopover(_:))
}

然后它会在黑暗模式下改变图像。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM