Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

macos - Trouble matching the vibrant background of a Yosemite NSMenuItem containing a custom view

I am attempting to add a custom view to an NSMenuItem in the OS X 10.10 Yosemite menu bar.

The custom view is simply an NSView background with an NSTextField “label”.

The problem is that the background NSView is given Yosemite-style vibrancy/transparency when added to the menu. The NSTextfield label is not.

Background colors do not match

Through the use of NSRectFillUsingOperation I've gotten this to look good for some background colors in Yosemite. But others continue to not match. When it is working, after manually "highlighting" the view, the original colors change and no longer match. I can dig up some example code for this if needed.

Then, when it is looking somewhat good in Yosemite, it looks terrible in 10.9 Mavericks.

I've also tried setting the wantsLayer property to YES to turn the view into a CALayer-backed view. This creates other issues such as text not anti-aliasing correctly against a clear background.

My Question:

How do I display a label on top of a NSMenuItem custom view? The label's background must exactly match the view's background. Solution must work in Yosemite and Mavericks.

Example code below:

self.statusItem = [[NSStatusBar systemStatusBar]
statusItemWithLength:NSVariableStatusItemLength];
[self.statusItem setTitle:@"TEST"];
[self.statusItem setHighlightMode:YES];
[self.statusItem setEnabled:YES];
[self.statusItem setTarget:self];

NSMenu *menu = [[NSMenu alloc] init];
[menu addItemWithTitle:@"Disabled menu item" action:nil keyEquivalent:@""];
[menu addItemWithTitle:@"Enabled menu item" action:@selector(enabled) keyEquivalent:@""];

NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(30, 20, 50, 20)];
label.stringValue = @"label";
label.editable = NO;
label.bordered = NO;
label.backgroundColor = [NSColor blueColor];
//label.backgroundColor = [NSColor clearColor];


PKMenuItemView *view = [[PKMenuItemView alloc] initWithFrame:NSMakeRect(0, 0, 200, 50)];
[view addSubview:label];

NSMenuItem *viewMenuItem = [[NSMenuItem alloc] init];
[viewMenuItem setView:view];
[menu addItem:viewMenuItem];

self.statusItem.menu = menu;

I've subclassed the NSView to override drawRect: and draw a colored background:

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    [[NSColor blueColor] setFill];
    NSRectFill(dirtyRect);
    //NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is surely kinda hack, but it worked for me. Try adding an NSImageView with empty image to your custom view. Image view must be occupy the whole view.

Using an NSImageView


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...