Як показати / приховати UIBarButtonItem?


251

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

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


Я просто відключив його і додав ярлик доступності, в якому говорилося, що функція кнопки недоступна.
Даніель Спрінгер

Відповіді:


263

Збережіть кнопку в міцній розетці (назвемо її 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];
}

Оскільки він зберігається у розетці, ви будете зберігати посилання на нього, навіть якщо його немає на панелі інструментів.


73
Щоб зробити цю роботу для правої кнопки в навігаційному контролері, я використав self.navigationItem.rightBarButtonItems та [self.navigationItem setRightBarButtonItems <prams>] замість toolBarItems та setToolBarItems.
MindSpiker

@MindSpiker: Так, ця ж техніка працює і для кнопок на навігаційній панелі.
lnafziger

1
чи потрібно мені знімати MyButton у dealloc?
Ван Дю Тран

48
Або Apple могла просто додати властивість .hidden. -_-
GeneCode

217

Я знаю, що ця відповідь запізнюється на це запитання. Однак це може допомогти, якщо хтось ще зіткнеться з подібною ситуацією.

В iOS 7, щоб приховати елемент панелі кнопки, ми можемо використовувати наступні дві техніки: -

  • використання SetTitleTextAttributes: - Це чудово працює на елементах панелі кнопок, таких як "Готово", "Зберегти" тощо. Однак це не працює для елементів, таких як Додати, символ сміття тощо (принаймні, не для мене), оскільки вони не є текстами.
  • використання TintColor: - Якщо у мене є елемент кнопки панелі під назвою "deleteButton": -

Щоб приховати кнопку, я використав такий код: -

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

Щоб знову показати кнопку, я використав такий код: -

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

[self.navigationItem.rightBarButtonItem setEnabled: NO]; [self.navigationItem.rightBarButtonItem setTintColor: [UIColor clearColor]];
Леон

3
Для Swift: deleteButton.enabled = false; deleteButton.tintColor = UIColor.clearColor()вимкнення та приховування та deleteButton.enabled = true; deleteButton.tintColor = nilповторне включення та показ як звичайне.
Unixmonkey

1
Мені подобається, що цей підхід дозволяє мені ввести логіку щодо того, чи потрібно відображати UIBarButton всередині цього класу чи ні. Причина, що працює лише з однією кнопкою, не відразу очевидна - це тому, що якщо приховати кнопку таким чином, вона все одно займе місце, тому у вас може бути порожній проміжок, якщо у вас є кілька кнопок.
SimplGy

Ваш перший підхід був ідеальним для мене. Я встановив UIColor.clearдля UIControlState.disabledі може показати / приховати кнопку з setEnabled. Звичайно, як ви заявили, це працює лише для текстових кнопок.
fl034

Якщо я довго натискаю на нього, поки воно не з'явиться у великому зображенні (можливо, для доступності), то навіть якщо isEnabled встановлено на false, він все ще працює.
Даніель Спрінгер

67

Ось простий підхід:

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

Я щойно запустив його на свій сітківку iPad, і .01 досить малий, щоб він не з’явився.


13
З усіх рішень цей був швидким, брудним та ефективним. Я також додав barbuttItem.enabled = НІ; оскільки я все-таки зможу отримати кнопку для запуску, якщо достатньо натиснути її.
Стіклі

1
Не працює для мене. Я думав, що це тому, що я використовую кнопку "Додати" із зображенням "+", але я спробував натомість кнопку "Налаштування" з текстом "Нове", і вона все ще не зникає. Увімкнення змінюється, тому я знаю, що виконується мій код. Будь-які ідеї? Зауважте, що ця кнопка створена на дошці розкадрів та має розвідку, тому я не хочу замість цього перейти на програмну кнопку
Rhubarb

19
Схоже, це не працює на панелі інструментів навігаційного контролера, але це робиться для інших панелей інструментів.
Дрю Розенберг

3
Він приховує його, але все ще реагує на крани. Для мене це працює як невидима кнопка.
Тібідабо

Якщо ви встановили глобальний відтінок кольору, використовуючи цей рядок self.window?.tintColor = APP_PRIMARY_COLORв AppDelegate, то це не буде працювати
Mehul Thakkar

60

Можна приховати кнопку на місці, не змінюючи її ширину і не знімаючи її з панелі. Якщо ви встановите стиль на звичайний, видаліть заголовок і відключите кнопку, вона зникне. Щоб відновити його, просто скасуйте зміни.

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

2
Це працювало для мене, просто встановивши btn.title = nil. Я також налаштований увімкнено = НІ, про всяк випадок ...
Pork 'n' Bunny

3
Встановлення кнопки buttonItem.title на нуль не працювало в iOS7. Кнопка не з’явилася знову, коли повертаєте її назад. Однак те, що працювало, було встановити buttonItem.title = @ "";
Марк Кноппер

42

Нижче моє рішення, хоча я шукав його для навігаційної панелі.

navBar.topItem.rightBarButtonItem = nil;

Тут "navBar" - це IBOutlet для NavigationBar у поданні в XIB. Тут я хотів приховати кнопку або показати її виходячи з якоїсь умови. Тому я тестую умову в "Якщо", і якщо це правда, я встановлюю кнопку для нуля в viewDidLoad метод цільового подання.

Це може не стосуватися вашої проблеми, але щось подібне, якщо ви хочете приховати кнопки в NavigationBar


Якщо ви хочете пізніше встановити rightBarButtonItemще раз, переконайтеся, що елемент кнопки зберігається у сильному IBOutlet, щоб він не відпускався, коли ви знімаєте його з навігаційної панелі.
Нейт

30

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


2
Але це все одно займе місце для цієї кнопки.
Макалеле

22

На даний момент я працюю на 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];

Дякую, це найкращий метод, який я знайшов. Просто переконайтеся, що ваші посилання на ваші кнопки є надійними.
jyoung

Також майте на увазі, що це працює лише за наявності у вас лише однієї кнопки. Приклад видалить ВСІ кнопки на цій стороні.
lnafziger

@jyoung Це працювало для мене, але чому це важливо, якщо посилання є сильним? Я не пробував іншого способу, але зазвичай не встановлюю це так, оскільки це не за замовчуванням.
Роберт

@Robert Ви хочете використовувати об'єкт пізніше, тому вам потрібно переконатися, що об’єкт не збирає сміття, коли ви встановите його на нуль. Якщо б нічого іншого не затримувало об’єкт, коли ви сказали елемент панелі кнопки, це нормально, щоб позбутися від нього, його кількість посилань буде 0, і сміття буде зібрано.
jyoung

14

Я використовував IBOutlets у своєму проекті. Тож моє рішення було:

@IBOutlet weak var addBarButton: UIBarButtonItem!

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

І коли вам потрібно буде знову показати цю панель, просто встановіть зворотні властивості.

У Swift 3 замість цього enableвикористовуйте isEnableвластивість.



12

iOS 8. UIBarButtonItem із зображенням на замовлення. Спробував багато різних способів, більшість із них не допомагали. Макс, рішенняsetTintColor не змінилося жодного кольору. Я сам це зрозумів, подумав, що комусь це буде корисно.

Для приховування:

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

Для показу:

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

9

Спробуйте в Swift , не оновлюйтеtintColor якщо у вас є дизайн для вашого UIBarButtonItem, наприклад, розмір шрифту в AppDelegate, це повністю змінить зовнішній вигляд вашої кнопки при появі.

У випадку з текстовою кнопкою зміна назви може дозволити кнопці "зникнути".

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

7

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

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

А потім isAccessibilityElementповернення до істинного, коли "показує" кнопку:

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

Якщо в моєму випадку елемент кнопки панелі все ще зайнятий, це не було проблемою, оскільки ми ховали / показували більшість лівих елементів кнопки правої смуги.


6
@IBDesignable class AttributedBarButtonItem: UIBarButtonItem {

    var isHidden: Bool = false {

        didSet {

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

А тепер просто поміняйте isHiddenвласність.


5

Поліпшення від відповіді @lnafziger

Збережіть свої Barbuttons у сильній розетці та зробіть це, щоб сховати / показати це:

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

5

Просто встановіть barButton.customView = UIView()і побачите трюк


Що ця відповідь робить, це дозволити працювати всі гнучкі розміри. Це насправді надзвичайно ефективна відповідь. Можливо, в поєднанні з розширенням, це було б ідеально.
Adrian_H

4

Немає способу "приховати" UIBarButtonItem, ви повинні вилучити його з superView та додати його назад, коли ви хочете його знову відобразити.


Це насправді не вірно - метод, описаний Максом, працює добре.
північ

1
nothernman - Макс насправді не правильний. Він насправді не приховує кнопку так, як більшість людей визначили б "ховання". Він просто робить це непомітним і відключає взаємодію користувачів. Кнопка все ще є і займає місце. Це зводиться до того, як ви хочете визначити "приховати", я вважаю, що дух оригінального питання хотів насправді видалити / додати, а не просто зробити його невидимим.
Майкл Петерсон

4

Це довгий шлях списку відповідей, але про всяк випадок, коли хтось хоче просту копію та вставити для швидкого рішення, ось він

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

Непогано, але потрібно вказати параметр UINavigationItem, а не UIToolbar, оскільки він просить приховати UIBarButtonItem. Я змінив вашу функцію на це: func hidToolbarItem (кнопка: UIBarButtonItem, панель інструментівToolbar: UINavigationItem) {var toolbarButtons: [UIBarButtonItem] = toolbar.rightBarButtonItems! toolbarButtons.removeAtIndex (панель інструментівButtons.indexOf (кнопка)!) панель інструментів.setRightBarButtonItems (панель інструментів Кнопки, анімовані: true)}, і це чудово працює
Kingalione

3

Один із способів зробити це - використовувати 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];


Однак він не закриє проміжок між іншими кнопками: коли він "прихований", на панелі інструментів буде порожня область.
lnafziger

@lnafziger Так, це правда, але я не читав згадування ОП про закриття розриву між кнопками, але це хороший момент, що слід зазначити.
iNoob

1
Дякую, ваша відповідь також корисна, але я думаю, що більшість людей, коли хочуть сховати кнопку на панелі інструментів, хочуть, щоб вона виглядала так, що її взагалі немає (без порожнього місця). Якщо це лівий чи правий, то це не мало би значення.
lnafziger

Хороші моменти, iNoob та Inafziger - я жодним чином не згадував це, але так, я вважаю за краще, щоб не було порожнього місця.
Сашко


2

Налаштування кольору тексту на чіткий колір, коли елемент панельної кнопки вимкнено, ймовірно, є більш чистим варіантом. Немає дивацтва, яке вам доведеться пояснювати в коментарі. Крім того, ви не знищуєте кнопку, тому ви все одно зберігаєте пов’язані з ними розкадровки.

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

Тоді, коли ви хочете, щоб пункт кнопки панелі був прихованим, ви можете просто зробити:

self.navigationItem.rightBarButton.enabled = NO;

Це кульгаво, що немає прихованої властивості, але це дає такий же результат.


1
У мене в правій кнопціBarButtonItem була кнопка. Тож я встановив його увімкнено на "НІ" і змінив його зображення на відключеному стані на нульове. Працював як шарм ... Спасибі
Skywalker

відмінна ідея, однак встановлення зображення на нуль не працювало для мене, мені довелося поставити трохи прозорого квадрата 20х20 як зображення
Лена Бру

2

Якщо у UIBarButtonItem є зображення замість тексту в ньому, ви можете зробити це, щоб приховати його: navigationBar.topItem.rightBarButtonItem.customView.alpha = 0.0;


2

Деякі допоміжні методи, на які я думав, поділяться на основі прийнятої відповіді 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];
    }
}

2

Ви можете легко отримати вид і сховати його таким чином

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


2

Ось розширення, яке впорається з цим.

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

1

Доповнюючи відповідь Елі Берка, якщо у вас 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];
    }
}

0

Потрібно маніпулювати масивом tool.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;

0

У IB, якщо залишити заголовок кнопки порожнім, вона не з’явиться (ніколи не ініціалізується?). Я роблю це часто під час розробки під час оновлень інтерфейсу користувача, якщо я хочу, щоб елемент панельної кнопки тимчасово зникав для збірки, не видаляючи його та не переглядаючи всі його посилання на розетку.

Це не має однакового ефекту під час виконання, якщо встановити заголовок кнопки на нуль, це не призведе до зникнення всієї кнопки. Вибачте насправді не відповідає на ваше запитання, але може бути корисним для деяких.

Редагувати: Цей трюк працює лише в тому випадку, якщо стиль кнопки встановлено як звичайний


0

Я додам тут своє рішення, оскільки я ще не міг його знайти тут. У мене є динамічна кнопка, зображення якої залежить від стану одного елемента керування. Найпростішим рішенням для мене було встановити зображення, nilякщо керування не було. Зображення оновлювалося щоразу, коли управління оновлювалось, і, таким чином, це було для мене оптимальним. Просто щоб переконатися , що я також встановити enabledв NO.

Налаштування ширини на мінімальне значення не працювало на iOS 7.


0

Маючи кредит @lnafziger, @MindSpiker, @vishal та ін. аль,

Найпростіший один вкладиш, до якого я прийшов за однією правою (або лівою) кнопкою смужки, - це:

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).


Це буде спрацьовувати, якщо у вас є лише одна кнопка, але якщо у вас є кілька кнопок, вам потрібно буде скористатися методом більше по лінії моєї відповіді.
lnafziger
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.