26

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

API の変更が表示されていないNSStatusBarNSStatusItem、変更が表示されていません。ユーザーが色合いを変更したときに簡単に変更できるように、通知または反応的なものであると想定しています。

画像を描画する現在のコードは、次のように囲まれてい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;
}
4

6 に答える 6

62

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


一部のアプリのステータス アイテム (PathFinder など) が既にダーク テーマで動作する理由は、StatusItem に独自のカスタム ビューを設定せず、StatusItem にテンプレート イメージのみを設定しているためです。

何かのようなもの:

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

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

マーベリックス

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

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

ヨセミテ

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

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

6 つの可能なステータス アイテムのスタイリング

非アクティブなメニューバーのステータス項目は、過去の単純な不透明度の変更とは対照的に、特定のスタイルを持つようになりました。無効な外観は、別の可能なバリエーションの 1 つです。この可能性のマトリックスには、他の追加の次元もあります。

API

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

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

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

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

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

現在の (非カスタム ビュー) API で実行できないことがある場合は、それに対する拡張要求を提出してください。StatusItems は、すべてのステータス アイテムで標準的な方法で動作または外観を提供する必要があります。


詳細な議論はhttps://devforums.apple.com/thread/234839にありますが、ほとんどすべてをここに要約しました。

于 2014-07-09T03:05:50.713 に答える
6

カスタムドラッグアンドドロップに従うようなことをしてしまいました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てビューのキーを監視するか、独自に行うことができます。

于 2014-07-09T16:31:05.843 に答える
2

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

于 2014-07-29T06:39:35.553 に答える
1

アプリケーションが 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";
    }
}
于 2014-07-08T13:26:33.793 に答える