Как показать / скрыть UIBarButtonItem?

Я создал панель инструментов в IB с несколькими кнопками. Я хотел бы иметь возможность скрыть / показать одну из кнопок в зависимости от состояния данных в главном окне.

UIBarButtonItem не имеет скрытого свойства, и любые примеры, которые я нашел до сих пор для сокрытия их, включают установку кнопок навигационной панели в ноль, что я не думаю, что я хочу делать здесь, потому что мне может понадобиться снова показать кнопку (не упомянуть, что, если я подключу свою кнопку к IBOutlet, если я установлю это на ноль, я не уверен, как я получу это назад).

39 ответов

Решение

Сохраните кнопку в надежной розетке (назовем ее myButton) и сделайте это, чтобы добавить / удалить его:

// Get the reference to the current toolbar buttons
NSMutableArray *toolbarButtons = [self.toolbarItems mutableCopy];

// This is how you remove the button from the toolbar and animate it
[toolbarButtons removeObject:self.myButton];
[self setToolbarItems:toolbarButtons animated:YES];

// This is how you add the button to the toolbar and animate it
if (![toolbarButtons containsObject:self.myButton]) {
    // The following line adds the object to the end of the array.  
    // If you want to add the button somewhere else, use the `insertObject:atIndex:` 
    // method instead of the `addObject` method.
    [toolbarButtons addObject:self.myButton];
    [self setToolbarItems:toolbarButtons animated:YES];
}

Поскольку он хранится в розетке, вы сохраните ссылку на него, даже если его нет на панели инструментов.

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

В iOS 7, чтобы скрыть элемент кнопки панели, мы можем использовать следующие два метода:

  • использование SetTitleTextAttributes: - Это прекрасно работает с кнопками панели, такими как "Готово", "Сохранить" и т. Д. Однако, это не работает с такими элементами, как "Добавить", "Корзина" и т. Д.(По крайней мере, не для меня), поскольку они не являются текстами.
  • использование TintColor: - Если у меня есть элемент кнопки панели под названием "deleteButton":-

Чтобы скрыть кнопку, я использовал следующий код: -

[self.deleteButton setEnabled:NO]; 
[self.deleteButton setTintColor: [UIColor clearColor]];

Чтобы снова показать кнопку, я использовал следующий код: -

[self.deleteButton setEnabled:YES];
[self.deleteButton setTintColor:nil];

Вот простой подход:

hide:  barbuttonItem.width = 0.01;
show:  barbuttonItem.width = 0; //(0 defaults to normal button width, which is the width of the text)

Я только что запустил его на своем сетчатке iPad, а 0,01 достаточно мал, чтобы он не появлялся.

Можно скрыть кнопку на месте, не меняя ее ширину и не удаляя ее с панели. Если вы установите простой стиль, удалите заголовок и отключите кнопку, он исчезнет. Чтобы восстановить его, просто отмените ваши изменения.

-(void)toggleBarButton:(bool)show
{
    if (show) {
        btn.style = UIBarButtonItemStyleBordered;
        btn.enabled = true;
        btn.title = @"MyTitle";
    } else {
        btn.style = UIBarButtonItemStylePlain;
        btn.enabled = false;
        btn.title = nil;
    }
}

Ниже мое решение, хотя я искал его для панели навигации.

navBar.topItem.rightBarButtonItem = nil;

Здесь "navBar" - это IBOutlet для Navigation Bar в представлении в XIB. Здесь я хотел скрыть кнопку или показать ее в зависимости от некоторых условий. Поэтому я проверяю условие в "Если", и если true, я устанавливаю кнопку в ноль в методе viewDidLoad целевого представления.

Это может не относиться к вашей проблеме, но что-то похожее, если вы хотите скрыть кнопки на панели навигации

Для Swift 3 и Swift 4 вы можете сделать это, чтобы скрыть UIBarButtomItem:

self.deleteButton.isEnabled = false
self.deleteButton.tintColor = UIColor.clear

И показать UIBarButtonItem:

self.deleteButton.isEnabled = true
self.deleteButton.tintColor = UIColor.blue

На tintColor Вы должны указать цвет источника, который вы используете для UIBarButtomItem

В настоящее время я использую OS X Yosemite Developer Preview 7 и Xcode 6 beta 6 для iOS 7.1, и мне подходит следующее решение:

  • Создать аутлет для UINavigationItemа также UIBarButtonItems
  • Запустите следующий код, чтобы удалить

    [self.navItem setRightBarButtonItem:nil];
    [self.navItem setLeftBarButtonItem:nil];
    
  • Запустите следующие коды, чтобы снова добавить кнопки

    [self.navItem setRightBarButtonItem:deleteItem];
    [self.navItem setLeftBarButtonItem:addItem];
    

Я использовал IBOutlets в своем проекте. Итак, мое решение было:

@IBOutlet weak var addBarButton: UIBarButtonItem!

addBarButton.enabled = false
addBarButton.tintColor = UIColor.clearColor()

И когда вам нужно будет снова показать эту панель, просто установите обратные свойства.

В Swift 3 вместо enable использование isEnable имущество.

self.dismissButton.customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];

iOS 8. UIBarButtonItem с пользовательским изображением. Перепробовал много разных способов, большинство из них не помогало. Решение Макса,setTintColor не менялся ни на какой цвет. Я сам понял это, подумал, что это кому-нибудь пригодится.

Для сокрытия:

[self.navigationItem.rightBarButtonItem setEnabled:NO];
[self.navigationItem.rightBarButtonItem setImage:nil];

Для показа:

[self.navigationItem.rightBarButtonItem setEnabled:YES];
[self.navigationItem.rightBarButtonItem setImage:image];

Я обнаружил еще одну морщину в tintColor а также isEnabled Подход, предложенный Максом и другими, - когда VoiceOver включен для специальных возможностей, а кнопка логически скрыта, курсор специальных возможностей все еще фокусируется на кнопке панели и заявляет, что она "затемнена" (т. е. потому что isEnabled установлено в false). Подход в принятом ответе не страдает от этого побочного эффекта, но я обнаружил, что нужно было еще обойти isAccessibilityElement ложь, когда "прячешь" кнопку:

deleteButton.tintColor = UIColor.clear
deleteButton.isEnabled = false
deleteButton.isAccessibilityElement = false

А потом настройка isAccessibilityElement Вернуться к истине, когда "показывает" кнопку:

deleteButton.tintColor = UIColor.blue
deleteButton.isEnabled = true
deleteButton.isAccessibilityElement = true

В моем случае не было проблем с тем, чтобы элемент панели кнопок все еще занимал пространство, поскольку мы скрывали / отображали самые левые элементы панели справа.

Попробуйте в Swift, не обновляйте tintColor если у вас есть какой-то дизайн для вашего UIBarButtonItem, например размер шрифта в AppDelegate, он полностью изменит внешний вид вашей кнопки при отображении.

В случае текстовой кнопки, изменение заголовка может позволить вашей кнопке "исчезнуть".

if WANT_TO_SHOW {
    myBarButtonItem.enabled = true
    myBarButtonItem.title = "BUTTON_NAME"
}else{
    myBarButtonItem.enabled = false
    myBarButtonItem.title = ""
}

Вот расширение, которое справится с этим.

extension UIBarButtonItem {

    var isHidden: Bool {
        get {
            return tintColor == .clear
        }
        set {
            tintColor = newValue ? .clear : .white //or whatever color you want
            isEnabled = !newValue
            isAccessibilityElement = !newValue
        }
    }

}

ИСПОЛЬЗОВАНИЕ:

myBarButtonItem.isHidden = true
@IBDesignable class AttributedBarButtonItem: UIBarButtonItem {

    var isHidden: Bool = false {

        didSet {

            isEnabled = !isHidden
            tintColor = isHidden ? UIColor.clear : UIColor.black
        }
    }
}

А теперь просто поменяй isHidden имущество.

Совершенствование От @lnafziger ответ

Сохраните ваши кнопки в надежной розетке и сделайте это, чтобы скрыть / показать это:

-(void) hideBarButtonItem :(UIBarButtonItem *)myButton {
    // Get the reference to the current toolbar buttons
    NSMutableArray *navBarBtns = [self.navigationItem.rightBarButtonItems mutableCopy];

    // This is how you remove the button from the toolbar and animate it
    [navBarBtns removeObject:myButton];
    [self.navigationItem setRightBarButtonItems:navBarBtns animated:YES];
}


-(void) showBarButtonItem :(UIBarButtonItem *)myButton {
    // Get the reference to the current toolbar buttons
    NSMutableArray *navBarBtns = [self.navigationItem.rightBarButtonItems mutableCopy];

    // This is how you add the button to the toolbar and animate it
    if (![navBarBtns containsObject:myButton]) {
        [navBarBtns addObject:myButton];
        [self.navigationItem setRightBarButtonItems:navBarBtns animated:YES];
    }
}

При необходимости используйте ниже функцию.

[self showBarButtonItem:self.rightBarBtn1];
[self hideBarButtonItem:self.rightBarBtn1];

Просто установите barButton.customView = UIView() и увидеть трюк

Нет способа "спрятать" UIBarButtonItem, вы должны удалить его из superView и добавить его обратно, когда вы захотите отобразить его снова.

Это длинный путь вниз по списку ответов, но на случай, если кто-то захочет легко скопировать и вставить для быстрого решения, вот оно

func hideToolbarItem(button: UIBarButtonItem, withToolbar toolbar: UIToolbar) {
    var toolbarButtons: [UIBarButtonItem] = toolbar.items!
    toolbarButtons.removeAtIndex(toolbarButtons.indexOf(button)!)
    toolbar.setItems(toolbarButtons, animated: true)
}

func showToolbarItem(button: UIBarButtonItem, inToolbar toolbar: UIToolbar, atIndex index: Int) {
    var toolbarButtons: [UIBarButtonItem] = toolbar.items!
    if !toolbarButtons.contains(button) {
        toolbarButtons.insert(button, atIndex: index)
        toolbar.setItems(toolbarButtons, animated:true);
    }
}

Один из способов сделать это - использовать initWithCustomView:(UIView *) свойство при выделении UIBarButtonItem, Подкласс для UIView будет иметь скрыть / показать свойство.

Например:

1. Иметь UIButton который вы хотите скрыть / показать.

2. Сделать UIButtonкак пользовательский вид. Подобно:

UIButton*myButton=[UIButton buttonWithType:UIButtonTypeRoundedRect];//your button

UIBarButtonItem*yourBarButton=[[UIBarButtonItem alloc] initWithCustomView:myButton];

3. Вы можете скрыть / показать myButton вы создали [myButton setHidden:YES];

Наконец, начиная с iOS 16+ ,UIBarButtonItemимеетisHiddenсвойство.

Итак, чтобы расширить существующие ответы, что-то вроде

      extension UIBarButtonItem {
    func show() {
        if #available(iOS 16.0, *) {
            isHidden = false
        } else {
            isEnabled = true
            tintColor = .white
        }
    }
    
    func hide() {
        if #available(iOS 16.0, *) {
            isHidden = true
        } else {
            isEnabled = false
            tintColor = .clear
        }
    }
}

Для версии Swift, вот код:

За UINavigationBar:

self.navigationItem.rightBarButtonItem = nil

self.navigationItem.leftBarButtonItem = nil

Если вы используете Swift 3

if (ShowCondition){
   self.navigationItem.rightBarButtonItem = self.addAsset_btn 
 } 
else {
   self.navigationItem.rightBarButtonItem = nil
 }

Если в UIBarButtonItem вместо текста есть изображение, вы можете сделать это, чтобы скрыть его: navigationBar.topItem.rightBarButtonItem.customView.alpha = 0.0;

Установка цвета текста в прозрачный цвет, когда элемент панели кнопок отключен, возможно, более чистый вариант. Там нет странностей, которые вы должны объяснить в комментарии. Также вы не уничтожаете кнопку, поэтому сохраняете любые связанные с ней раскадровки.

[self.navigationItem.rightBarButtonItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor clearColor]}
                                                      forState:UIControlStateDisabled];

Затем, когда вы захотите скрыть элемент панели кнопок, вы можете просто сделать:

self.navigationItem.rightBarButton.enabled = NO;

Жаль, что нет скрытого свойства, но это дает тот же результат.

Вы можете легко получить вид и скрыть это таким образом

let view: UIView = barButtonItem.valueForKey("view") as! UIView
view.hidden = true

Некоторые вспомогательные методы, которыми я поделился, основываясь на принятом ответе lnafziger, так как у меня есть несколько панелей инструментов и несколько кнопок на каждой:

-(void) hideToolbarItem:(UIBarButtonItem*) button inToolbar:(UIToolbar*) toolbar{
    NSMutableArray *toolbarButtons = [toolbar.items mutableCopy];
    [toolbarButtons removeObject:button];
    [toolbar setItems:toolbarButtons animated:NO];
}

-(void) showToolbarItem:(UIBarButtonItem*) button inToolbar:(UIToolbar*) toolbar atIndex:(int) index{
    NSMutableArray *toolbarButtons = [toolbar.items mutableCopy];
    if (![toolbarButtons containsObject:button]){
        [toolbarButtons insertObject:button atIndex:index];
        [self setToolbarItems:toolbarButtons animated:YES];
    }
}

Справочный ответ @haste

      extension UIBarButtonItem {
    var isHidden: Bool {
        set {
            if #available(iOS 16.0, *) {
                isHidden = newValue
            } else {
                isEnabled = !newValue
                tintColor = newValue ? .clear : nil
            }
        }
        
        get {
            if #available(iOS 16.0, *) {
                return isHidden
            } else {
                return isEnabled == false && tintColor == .clear
            }
        }
    }
}

Вы можете использовать атрибуты текста, чтобы скрыть кнопку панели:

barButton.enabled = false
barButton.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.clearColor()], forState: .Normal)

Также посмотрите мое решение с расширением UIBarButtonItem для аналогичного вопроса: сделать UIBarButtonItem исчезнуть с помощью быстрой IOS

Дополняя ответ Эли Бёрка, если ваш UIBarButtonItemимеет фоновое изображение вместо заголовка, вы можете использовать код:

-(void)toggleLogoutButton:(bool)show{
    if (show) {
        self.tabButton.style = UIBarButtonItemStyleBordered;
        self.tabButton.enabled = true;
        UIImage* imageMap = [UIImage imageNamed:@"btn_img.png"];
        [((UIButton *)[self.tabButton customView]) setBackgroundImage:imageMap forState:UIControlStateNormal];
    } else {
        self.tabButton.style = UIBarButtonItemStylePlain;
        self.tabButton.enabled = false;
        [((UIButton *)[self.tabButton customView]) setBackgroundImage:nil forState:UIControlStateNormal];
    }
}

У меня была проблема, что у меня было 2 leftBarButtonItems. На Mac Catalyst firstButton указывал на действие, которое не поддерживалось: запись видео с помощью AVFoundation. На Mac Catalyst действовала только вторая кнопка: используйте UIImagePickerController.

Итак, на Mac Catalyst мне пришлось указать первый UIBarButtonItem на secondButton и всегда скрыть второй UIBarButtonItem. На iOS должны отображаться обе кнопки. Это было моим решением:

#if TARGET_OS_MACCATALYST
        self.navigationItem.leftBarButtonItem = self.secondButton;
        NSUInteger count = [self.navigationItem.leftBarButtonItems count];
        for (NSUInteger i = 0; i < count; i++) {
            UIBarButtonItem *thisButton = [self.navigationItem.leftBarButtonItems objectAtIndex:i];
            if (i == 1) {
                thisButton.enabled = NO;
                thisButton.tintColor = [UIColor clearColor];
            }
        }
#else
        self.navigationItem.leftBarButtonItem = self.firstButton;
#endif

Надеюсь, это поможет кому-то с аналогичной проблемой.

Другие вопросы по тегам