Как скрыть элемент меню в настраиваемом представлении?

Я использую очень простое настраиваемое представление (содержащее только NSTextField и NSSegmentedControl только для чтения) в NSMenuItem (с использованием метода -setView:). Эта часть работает как положено.

Проблема вот в чем: в методе делегата -menuNeedsUpdate: NSMenu я условно скрываю пункт меню. Когда я вызываю [item setHidden:YES], пункт меню с настраиваемым видом не скрывается, но другие «ванильные» элементы меню скрываются.

Мое настраиваемое представление построено в собственном XIB, и я получаю к нему доступ через настраиваемый NSViewController.

Обновить

Пункт меню остается видимым, даже если я устанавливаю флажок «Скрытый» в Interface Builder и удаляю строку, в которой он скрыт в коде.

Обновление 2

Я также пробовал установить hidden в пользовательском представлении до и после установки hidden в пункте меню. Результат такой, как если бы пункт меню не был скрыт, но вид был скрыт; элементы управления представления не видны, но все еще есть пробел на том месте, где они должны быть.

Обновление 3

Я изменил пример кода Apple MenuItemView, чтобы скрыть один из элементы меню после его добавления (вставьте [menuItem setHidden:YES]; в строку 87), и он имеет тот же эффект, что и в моем коде (то есть, нет).

Я начинаю думать, что единственный способ скрыть этот пункт меню - установить его вид на nil, когда мне нужно скрыть его, и вернуть обратно, когда мне нужно его показать, но это не кажется необходимым.

Обновление 4

Используя ответ Майка ниже, вот код, который я использую:

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

person Dov    schedule 03.05.2011    source источник


Ответы (4)


Можете ли вы при необходимости удалить / повторно добавить элемент вместо того, чтобы скрывать его?

 [rootMenu removeItemAtIndex: 23];
person Rayfleck    schedule 03.05.2011
comment
Я пытался обойтись без того, чтобы этот конкретный контроллер имел какие-либо ссылки на конкретный пункт меню, но это может быть лучшим выходом. - person Dov; 03.05.2011
comment
Я должен признать, что у меня глубокое предубеждение: сделать это, отправить, оставить выяснять, почему это сработало / не сработало, в качестве упражнения для читателя. Удачи. - person Rayfleck; 03.05.2011

В меню метода делегата menu: updateItem: atIndex: shouldCancel: я нахожу свой пользовательский элемент меню просмотра по тегу и устанавливаю его вид равным нулю, если он скрыт, или назначаю пользовательский вид, если он виден:

- (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;
}
person askh    schedule 09.03.2012

Мне пришлось переопределить метод 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])];
}

}

person Francis McGrew    schedule 03.05.2011
comment
Где определяется menuItemHeight? Я не вижу этого в документации для NSMenuItem. - person Dov; 03.05.2011
comment
Это мой собственный метод (я думаю, что высота по умолчанию 19,0, вы можете просто заменить это) - person Francis McGrew; 03.05.2011

В Swift вы можете переопределить isHidden и установить view соответственно:

class PositionHeaderMenuItem: NSMenuItem {
    let customView = SomeCustomView()

    override var isHidden: Bool {
        didSet {
            if isHidden {
                view = nil
            } else {
                view = customView
            }
        }
    }
}
person Honghao Zhang    schedule 09.06.2020