簡體   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