web-dev-qa-db-ja.com

NSStatusItemは暗い色合いの画像を変更します

OSX 10.10ベータ3では、Appleは暗い色合いのオプションをリリースしました。残念ながら、これはほとんどすべてのステータスバーアイコン(私が見たAppleとPath Finderを除く)を意味します。私を含めて、暗い背景で暗いままにします。暗い色合いが適用されたときの代替画像を提供するにはどうすればよいですか?

NSStatusBarまたはNSStatusItemに変更を示す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;
}
23
Joel Fischer

TL; DR:ダークテーマで特別なことをする必要はありません。 NSStatusItem(またはNSStatusBarButton)にテンプレート画像を指定すると、メニューバーのコンテキストで正しくスタイルが設定されます。


一部のアプリのステータスアイテム(PathFinderなど)がすでにダークテーマで機能している理由は、それらがStatusItemに独自のカスタムビューを設定しておらず、StatusItemにテンプレートイメージを設定しているだけだからです。

何かのようなもの:

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

これは、Mavericks以前、Yosemiteおよび将来のリリースで期待されるとおりに機能しますAppKitが、ステータスアイテムの状態に応じて画像のすべてのスタイル設定を実行できるためです。

マーベリックス

マーベリックス(およびそれ以前)では、アイテムのユニークなスタイルは2つしかありませんでした。押されていない、押されている。これらの2つのスタイルは、それぞれ純粋に黒と純粋に白に見えました。 (実際には、「純粋な黒」は完全に正しいわけではありません。わずかに挿入されたように見える小さな効果がありました)。

可能な状態は2つしかないため、ステータスバーアプリは、強調表示された状態に応じて黒または白を描画するだけで、独自のビューを設定し、同じ外観を簡単に取得できます。 (ただし、純粋に黒ではなかったため、アプリは画像に効果を組み込むか、ほとんど目立たない場所のアイコンに満足する必要がありました)。

ヨセミテ

ヨセミテには、少なくとも32のユニークなアイテムのスタイリングがあります。 Unpressed in Dark Themeは、そのうちの1つにすぎません。アプリが独自のアイテムのスタイリングを実行し、すべてのコンテキストで正しく見えるようにするための実用的な(または非実用的な)方法はありません。

これらの可能なスタイリングの6つの例を次に示します。

Six possible status item stylings

非アクティブなメニューバーのステータスアイテムは、以前のような単純な不透明度の変更とは対照的に、特定のスタイルを持つようになりました。無効な外観は、もう1つの可能なバリエーションです。この可能性のマトリックスには、他にもdimensionsが追加されています。

API

NSStatusItemのviewプロパティとして設定された任意のビューには、これらのバリエーションをすべてキャプチャする方法がないため、10.10では非推奨になっています(およびその他の関連API)。

ただし、シード3ではNSStatusItemに新しいAPIが導入されています。

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

このAPIにはいくつかの目的があります。

  1. アプリは、独自のカスタムビューを設定せずに、ステータスアイテムの画面位置を取得(またはポップオーバーを表示)できるようになりました。
  2. NSStatusItemのimagetitlesendActionOn:などのAPIが不要になります。
  3. 新しいAPIのクラスを提供します:つまり、looksDisabled。これにより、アプリは、カスタムイメージを必要とせずに、標準の無効/オフスタイル(オフの場合のBluetooth/Time Machineなど)を取得できます。

現在の(カスタムビューではない)APIで実行できないことがある場合は、拡張リクエストを提出してください。 StatusItemsは、すべてのステータス項目で標準となる方法で動作または外観を提供する必要があります。


詳細については https://devforums.Apple.com/thread/234839 を参照してください。ただし、ここではほとんどすべてを要約しています。

59
Taylor

私はカスタムドラッグアンドドロップに続くようなことをすることになります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キーを監視するか、自分で調整することができます。

5
Cai

NSStatusItemの基本的なラッパーを作成しました。これを使用して、ステータスバーのカスタムビューで10.10以前のサポートを提供できます。ここで見つけることができます: https://github.com/noahsmartin/YosemiteMenuBar 基本的な考え方は、カスタムビューをNSImageに描画し、この画像をステータスバーアイテムのテンプレート画像として使用することです。このラッパーは、クリックイベントをカスタムビューに転送するため、10.10より前と同じ方法で処理できます。プロジェクトには、ステータスバーのカスタムビューでYosemiteMenuBarを使用する方法の基本的な例が含まれています。

2
Noah

最新の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(_:))
}

次に、ダークモードのときに画像を変更します。

1
zhi.yang

ただし、ステータスの変化を監視したい場合に備えて、可能です。また、ライト/ダークモードを決定するためのより良い方法があることも知っていますが、今はそれを覚えています。

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

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

アプリケーションがGUI要素を描画すると、[NSAppearance currentAppearance]を介してその外観を取得できます。この要素自体には、次のようなものを保持するnameプロパティがあります。

NSAppearanceNameVibrantDark->NSAppearanceNameAqua->NSAppearanceNameAquaMavericks

最初の部分は外観の名前であり、NSAppearanceNameVibrantDarkまたは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";
    }
}
1
max