Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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); } 
like image 960
pkamb Avatar asked Nov 10 '14 19:11

pkamb


1 Answers

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

like image 130
benchman Avatar answered Oct 21 '22 20:10

benchman