How do you hide a Menu Item with a custom view?
I am using a very simple custom view (containing only a read-only NSTextField and an NSSegmentedControl) in an NSMenuItem (using the -setView:
method). This part works as expected.
Here's the problem: in the -menuNeedsUpdate:
NSMenu delegate method I'm cond开发者_如何学Goitionally hiding the menu item. When I call [item setHidden:YES]
, the menu item with a custom view doesn't hide, but other 'vanilla' menu items do.
My custom view is built in its own XIB, and I'm accessing it through a custom NSViewController.
Update
The menu item stays visible even if I check the Hidden checkbox in Interface Builder, and remove the line where it's hidden in code.
Update 2
I also tried setting hidden
on the custom view before and after setting hidden
on the menu item. The result is as if the menu item is not hidden, but the view is; the view's controls aren't visible, but there is still a gap where they should be.
Update 3
I modified Apple's MenuItemView sample code to hide one of the menu items after it's added (insert [menuItem setHidden:YES];
at line 87), and it has the same effect as in my code (which is to say, none).
I'm starting to think the only way to hide this menu item will be to set its view to nil
when I need to hide it and put it back when I need to show it, but it doesn't seem that should be necessary.
Update 4
Using Mike's answer below, here is the code I'm using:
// Declared in the header file
IBOutlet NSMenuItem *previousMenuItem;
IBOutlet NSMenuItem *togglingMenuItem; //Needs to be RETAINED
. . .
- (void)menuNeedsUpdate:(NSMenu *)menu {
BOOL hideItem = YES; // Some criteria, obviously
// Remove the menu item, if it was already present
if ([menu indexOfItem:togglingMenuItem] >= 0) {
[menu removeItem:togglingMenuItem];
}
// Put it back if it should be visible
if (!onePageVisible) {
[menu insertItem:togglingMenuItem
atIndex:[menu indexOfItem:previousMenuItem] + 1];
}
}
Rather than hiding an item, can you remove/re-add as needed?
[rootMenu removeItemAtIndex: 23];
In menu delegate method menu:updateItem:atIndex:shouldCancel: i find my custom view menu item by tag and set it's view to nil if it is hidden or assign custom view if visible:
- (BOOL)menu:(NSMenu *)menu
updateItem:(NSMenuItem *)item
atIndex:(NSInteger)index
shouldCancel:(BOOL)shouldCancel
{
if ([item tag] == CUSTOM_VIEW_TAG)
{
[item setView:[item isHidden]?nil:customView];
return NO; //we've done our dirty work
}
return YES;
}
In Swift, you can override isHidden
and set view
accordingly:
class PositionHeaderMenuItem: NSMenuItem {
let customView = SomeCustomView()
override var isHidden: Bool {
didSet {
if isHidden {
view = nil
} else {
view = customView
}
}
}
}
I had to override NSMenuItem's setHidden: method and set the view's height to zero if hidden, like so:
- (void) setHidden:(BOOL)flag {
[super setHidden:flag];
NSView *view = [self view];
[view setHidden:flag];
// if our view is hidden, give it a zero height so it won't draw at all
if (flag)
[view setFrameSize:NSMakeSize([view frame].size.width, 0)];
else {
[view setFrameSize:NSMakeSize([view frame].size.width, [self menuItemHeight])];
}
}
精彩评论