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

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

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

Ответы на вопрос(30)

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

ЗаUINavigationBar:

self.navigationItem.rightBarButtonItem = nil

self.navigationItem.leftBarButtonItem = nil

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

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

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

Для показа:

[self.navigationItem.rightBarButtonItem setEnabled:YES];
[self.navigationItem.rightBarButtonItem setImage:image];
Решение Вопроса

Сохраните свою кнопку вstrong розетка (назовем это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];
}

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

 22 февр. 2016 г., 12:29
Или Apple может просто добавить скрытое свойство. -_-
 12 нояб. 2012 г., 20:11
Чтобы заставить это работать для моей правой кнопки в контроллере навигации, я использовал self.navigationItem.rightBarButtonItems и [self.navigationItem setRightBarButtonItems & lt; prams & gt;] вместо toolBarItems и setToolBarItems.
 12 нояб. 2012 г., 20:43
@MindSpiker: Да, та же техника работает и для кнопок на панели навигации.
 06 окт. 2013 г., 05:53
@VanDuTran: Нет, смотрите:stackoverflow.com/q/7906804/937822
 05 окт. 2013 г., 16:27
я должен обнулить myButton в dealloc?

С благодарностью @lnafziger, @MindSpiker, @vishal, et. аль,

Простейший вкладыш, к которому я пришел для одной правой (или левой) кнопки панели:

self.navigationItem.rightBarButtonItem = <#StateExpression#>
    ? <#StrongPropertyButton#> : nil;

Как в:

@interface MyClass()

@property (strong, nonatomic) IBOutlet UIBarButtonItem *<#StrongPropertyButton#>;

@end

@implementation

- (void) updateState
{
    self.navigationItem.rightBarButtonItem = <#StateExpression#>
        ? <#StrongPropertyButton#> : nil;
}

@end

Я проверил это, и оно работает для меня (с элементом кнопки сильной панели, подключенным через IB).

 26 апр. 2014 г., 18:20
Это будет работать, если у вас есть только одна кнопка, но если у вас есть несколько кнопок, вам нужно будет использовать метод больше в соответствии с моим ответом.

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

 12 сент. 2018 г., 16:20
Что делает этот ответ, так это позволяет всем гибким настройкам работать. Это действительно очень эффективный ответ. Вероятно, в сочетании с расширением было бы идеально.

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

@IBDesignable class AttributedBarButtonItem: UIBarButtonItem {

    var isHidden: Bool = false {

        didSet {

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

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

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

-(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;
    }
}
 07 авг. 2013 г., 17:18
Это сработало для меня, просто установив btn.title = nil. Я также включил параметр = НЕТ, на всякий случай ...
 01 окт. 2013 г., 15:23
Установка для buttonItem.title значения nil не работает для меня в iOS7. Кнопка не появилась снова при ее установке. Однако то, что сработало, это настройка [email protected]" & Quot ;;

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

 21 окт. 2014 г., 05:14
На самом деле это не так - метод, описанный Максом, работает хорошо.
 07 авг. 2015 г., 21:52
nothernman - Макс на самом деле не правильно. Он на самом деле не скрывает кнопку так, как большинство людей определяет «скрытие». Он просто делает его невидимым и отключает взаимодействие с пользователем. Кнопка все еще там и занимает место. Все сводится к тому, как вы хотите определить «скрыть», я думаю, что дух первоначального вопроса заключался в том, чтобы фактически удалить / добавить его, а не просто сделать его невидимым.

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

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

use SetTitleTextAttributes :- This works great on bar button items like "Done", "Save" etc. However, it does not work on items like Add, Trash symbol etc.(atleast not for me) since they are not texts. use TintColor :- If I have a bar button item called "deleteButton" :-

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

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

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

[self.deleteButton setEnabled:YES];
[self.deleteButton setTintColor:nil];
 31 дек. 2018 г., 00:31
Если я долго нажимаю на него, пока он не появится на большом изображении (вероятно, для доступности), то даже если для isEnabled установлено значение false, он все равно работает.
 02 июл. 2015 г., 23:02
[self.navigationItem.rightBarButtonItem setEnabled: NO]; [self.navigationItem.rightBarButtonItem setTintColor: [UIColor clearColor]];
 11 сент. 2018 г., 17:18
Ваш первый подход был идеальным для меня. Я поставилUIColor.clear заUIControlState.disabled и может показать / скрыть кнопку сsetEnabled, Конечно, как вы сказали, это работает только для текстовых кнопок.
 09 июл. 2015 г., 00:04
Для Свифта:deleteButton.enabled = false; deleteButton.tintColor = UIColor.clearColor() отключить и скрыть, иdeleteButton.enabled = true; deleteButton.tintColor = nil чтобы снова включить и показать как обычно.
 15 нояб. 2016 г., 20:54
Мне нравится, что этот подход позволяет мне определить логику отображения UIBarButton внутри этого класса. Причина, по которой она работает только с одной кнопкой, не сразу очевидна - это потому, что если вы скрываете кнопку таким образом, она все равно будет занимать место, поэтому у вас может быть пустой пробел, если у вас несколько кнопок.

If you are using Swift 3

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

Один из способов сделать это - использовать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];

 05 апр. 2012 г., 05:36
Спасибо, ваш ответ тоже полезен, но я думаю, что большинство людей, когда они хотят скрыть кнопку на панели инструментов, хотят, чтобы она выглядела так, как будто ее вообще нет (без пустой области). Если он левый или правый, он не будет иметь большого значения.
 05 апр. 2012 г., 05:32
@ lnafziger Да, это правда, но я не читал упоминание OP о сокращении разрыва между кнопками, но это хорошее замечание.
 05 апр. 2012 г., 05:29
Тем не менее, он не сократит разрыв между другими кнопками: когда он «скрыт»; на панели инструментов будет пустое место.
 Sasha06 апр. 2012 г., 03:33
Хорошие моменты, iNoob и Inafziger - я не упомянул об этом в любом случае, но да, я бы предпочел, чтобы не было пустого места.

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

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

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

Для 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

 19 дек. 2017 г., 11:55
Но это все равно займет место для этой кнопки.

Вам нужно манипулировать массивом toolbar.items.

Вот код, который я использую, чтобы скрыть и отобразить кнопку Готово. Если ваша кнопка находится на крайнем краю панели инструментов или между другими кнопками, другие ваши кнопки будут перемещаться, поэтому, если вы хотите, чтобы ваша кнопка просто исчезла, поместите эту кнопку как последнюю кнопку к центру. Я оживляю движение кнопки для эффекта, мне это очень нравится.

-(void)initLibraryToolbar {

    libraryToolbarDocumentManagementEnabled = [NSMutableArray   arrayWithCapacity:self.libraryToolbar.items.count];
    libraryToolbarDocumentManagementDisabled = [NSMutableArray arrayWithCapacity:self.libraryToolbar.items.count];
    [libraryToolbarDocumentManagementEnabled addObjectsFromArray:self.libraryToolbar.items];
    [libraryToolbarDocumentManagementDisabled addObjectsFromArray:self.libraryToolbar.items];
    trashCan = [libraryToolbarDocumentManagementDisabled objectAtIndex:3];
    mail = [libraryToolbarDocumentManagementDisabled objectAtIndex:5];
    [libraryToolbarDocumentManagementDisabled removeObjectAtIndex:1];
    trashCan.enabled = NO;
    mail.enabled = NO;
    [self.libraryToolbar setItems:libraryToolbarDocumentManagementDisabled animated:NO];

}

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

[self.libraryToolbar setItems:libraryToolbarDocumentManagementEnabled animated:YES];
trashCan.enabled = YES;
mail.enabled = YES; 

или скрыть свою кнопку

[self.libraryToolbar setItems:libraryToolbarDocumentManagementDisabled animated:YES];
trashCan.enabled = NO;
mail.enabled = NO;

Дополняя ответ Эли Бёрка, если ваш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];
    }
}

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

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);
    }
}
 08 апр. 2016 г., 16:09
Неплохо, но вы должны указать UINavigationItem в качестве параметра, а не UIToolbar, потому что он просит скрыть UIBarButtonItem. Я изменил вашу функцию следующим образом: func hideToolbarItem (кнопка: UIBarButtonItem, с панелью инструментов Toolbar: UINavigationItem) {var toolbarButtons: [UIBarButtonItem] = toolbar.rightBarButtonItems! toolbarButtons.removeAtIndex (toolbarButtons.indexOf (button)!) toolbar.setRightBarButtonItems (toolbarButtons, animated: 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];
    }
}

Я добавлю свое решение здесь, поскольку пока не смог найти упомянутое здесь. У меня есть динамическая кнопка, изображение которой зависит от состояния одного элемента управления. Самым простым решением для меня было установить изображение наnil если контроля не было. Изображение обновлялось каждый раз, когда обновлялся элемент управления, и, таким образом, это было оптимальным для меня. Просто чтобы быть уверенным, что я также установилenabled вNO.

Установка ширины в минимальное значение не работает на iOS 7.

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

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

В IB, если вы оставите заголовок кнопки пустым, он не появится (никогда не инициализируется?). Я делаю это часто во время разработки во время обновлений пользовательского интерфейса, если я хочу, чтобы элемент панели кнопок временно исчезал для сборки, не удаляя ее и не удаляя все ссылки на выходы.

Это не имеет такого же эффекта во время выполнения, установка значения кнопки на ноль не приведет к исчезновению всей кнопки. Извините, действительно не отвечаю на ваш вопрос, но может быть полезным для некоторых.

Изменить. Этот прием работает только в том случае, если стиль кнопки установлен на обычный

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

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

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

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

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

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

Create outlet for UINavigationItemand UIBarButtonItems

Run following code to remove

[self.navItem setRightBarButtonItem:nil];
[self.navItem setLeftBarButtonItem:nil];

Run following codes to add buttons again

[self.navItem setRightBarButtonItem:deleteItem];
[self.navItem setLeftBarButtonItem:addItem];
 17 нояб. 2015 г., 02:52
@jyoung Это сработало для меня, но почему это важно, если ссылка сильна? Я не пробовал другой способ, но обычно не устанавливал его таким образом, поскольку он не используется по умолчанию.
 14 нояб. 2015 г., 17:54
Также имейте в виду, что это работает, только если у вас есть только одна кнопка. Пример удалит ВСЕ кнопки на этой стороне.
 27 июл. 2015 г., 05:50
Спасибо, это лучший метод, который я также нашел. Просто убедитесь, что ваши ссылки на ваши кнопки сильны.
 18 нояб. 2015 г., 17:27
@ Роберт. Вы хотите использовать объект позднее, поэтому вам нужно убедиться, что объект не получает мусора, когда вы устанавливаете его на ноль. Если ничто иное не удерживало объект, когда вы сказали элементу панели кнопок, что все в порядке, избавиться от него, его счетчик ссылок будет равен 0, и он будет собирать мусор.

Улучшение От @lnafziger ответ

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

-(void) hideBarButtonItem :(UIBarButtonItem *)myButton {
    // Get the refer,ence 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];

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

@IBOutlet weak var addBarButton: UIBarButtonItem!

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

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

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

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

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

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

self.navigationItem.rightBarButton.enabled = NO;

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

 23 дек. 2015 г., 16:03
отличная идея, однако установка значения NULL для меня не сработала, мне пришлось поместить небольшой прозрачный квадрат размером 20x20 в качестве изображения
 10 дек. 2015 г., 14:55
У меня была кнопка внутри RightBarButtonItem. Поэтому я установил для его разрешения значение «НЕТ» и изменил его изображение в отключенном состоянии на ноль. Работал как шарм ... спасибо
 14 апр. 2016 г., 03:56
это бриллс .... отлично работает для текстовых / пользовательских кнопок

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

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 достаточно мал, чтобы он не появлялся.

 29 мая 2015 г., 00:49
похоже, не работает в ios 8 xcode 6.3
 02 июн. 2016 г., 22:07
не работает в ios 9 xcode 7.3.1
 02 окт. 2012 г., 21:23
Похоже, что он не работает на панели инструментов контроллера навигации, но он работает для других панелей инструментов.
 26 сент. 2012 г., 22:52
Из всех решений это было быстрое, грязное и эффективное. Я также добавил barbuttItem.enabled = NO; так как я все еще могу заставить кнопку сработать, если нажму достаточно.
 24 июл. 2013 г., 15:59
Это скрывает это, но это все еще отвечает на сигналы. Для меня это действует как невидимая кнопка.

In case the UIBarButtonItem has an image instead of the text in it you can do this to hide it: navigationBar.topItem.rightBarButtonItem.customView.alpha = 0.0;

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

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

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

navBar.topItem.rightBarButtonItem = nil;

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

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

 22 окт. 2016 г., 14:01
Если вы хотите позже установитьrightBarButtonItem еще раз, убедитесь, что элемент кнопки хранится вstrong IBOutlet, чтобы он не выпускался при снятии с навигационной панели.

Ваш ответ на вопрос