如何使用自定义视图隐藏菜单项?

时间:2011-05-03 14:08:34

标签: objective-c cocoa macos nsmenuitem nsmenu

我在NSMenuItem中使用一个非常简单的自定义视图(仅包含只读NSTextField和NSSegmentedControl)(使用-setView:方法)。这部分按预期工作。

问题出现了:在-menuNeedsUpdate: NSMenu委托方法中,我有条件地隐藏了菜单项。当我拨打[item setHidden:YES]时,带有自定义视图的菜单项不会隐藏,但其他“香草”菜单项会隐藏。

我的自定义视图是在自己的XIB中构建的,我通过自定义的NSViewController访问它。

更新

即使我选中Interface Builder中的隐藏复选框,菜单项仍然可见,并删除隐藏在代码中的行。

更新2

我还尝试在菜单项上设置hidden之前和之后在自定义视图上设置hidden。结果就好像菜单项没有隐藏,但视图是;视图的控件不可见,但它们应该存在差距。

更新3

我修改了Apple的MenuItemView示例代码以隐藏其中一个菜单项(在第87行插入[menuItem setHidden:YES];),它与我的代码具有相同的效果(也就是说,没有)。

我开始认为隐藏此菜单项的唯一方法是将其视图设置为nil,当我需要隐藏它并在需要显示它时将其恢复,但它不会似乎应该是必要的。

更新4

使用Mike的答案,下面是我正在使用的代码:

// 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];
    }
}

4 个答案:

答案 0 :(得分:1)

您可以根据需要删除/重新添加项目,而不是隐藏项目吗?

 [rootMenu removeItemAtIndex: 23];

答案 1 :(得分:0)

我必须覆盖NSMenuItem的setHidden:方法,并在隐藏时将视图的高度设置为零,如下所示:

- (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])];
}

}

答案 2 :(得分:0)

在菜单委托方法菜单中:updateItem:atIndex:shouldCancel:我按标签查找自定义视图菜单项,如果隐藏则将其视图设置为nil,如果可见则指定自定义视图:

- (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;
}

答案 3 :(得分:0)

在Swift中,您可以覆盖isHidden并相应地设置view

class PositionHeaderMenuItem: NSMenuItem {
    let customView = SomeCustomView()

    override var isHidden: Bool {
        didSet {
            if isHidden {
                view = nil
            } else {
                view = customView
            }
        }
    }
}