如何显示/隐藏UIBarButtonItem?


251

我用几个按钮在IB中创建了一个工具栏。我希望能够根据主窗口中数据的状态来隐藏/显示按钮之一。

UIBarButtonItem 没有隐藏属性,到目前为止,我发现的所有隐藏它们的示例都涉及将导航栏按钮设置为nil,我认为我不想在这里这样做,因为我可能需要再次显示按钮(不是要提到的是,如果我将按钮连接到IBOutlet,如果将其设置为nil,则不确定如何将其取回)。


我只是禁用了它,并添加了一个可访问性标签,说该按钮的功能不可用。
丹尼尔·施普林格

Answers:


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,2012年

@MindSpiker:是的,他同样的技术也适用于导航栏上的按钮。
lnafziger

1
我是否必须在dealloc中将myButton设置为nil?
Van Du Tran 2013年

48
或者Apple可以只添加.hidden属性。-_-
GeneCode

217

我知道这个问题迟到了。但是,如果其他人也遇到类似的情况,这可能会有所帮助。

在iOS 7中,要隐藏条形按钮项,我们可以使用以下两种技术:

  • 使用SetTitleTextAttributes:-这对“完成”,“保存”等条形按钮项目效果很好。但是,对于诸如“添加”,“废纸symbol”符号等项目(至少对我来说不是),它不起作用,因为它们不是文本。
  • 使用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]];
2015年

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 = NO; 因为如果我按下足够多的按钮,仍然可以触发按钮。
Stickley 2012年

1
对我不起作用。我以为是因为我使用的是带有“ +”图像的“添加”按钮,但是我尝试使用带有“新建”文本的“自定义”按钮,但它仍然没有消失。启用更改,因此我知道我的代码正在执行。有任何想法吗?请注意,此按钮是在情节提要中创建的,并且具有序列号,因此我不想更改为程序化按钮
Rhubarb 2012年

19
它似乎在导航控制器工具栏中不起作用,但对其他工具栏则有效。
德鲁·罗森伯格

3
它隐藏了它,但是它仍然对水龙头做出反应。对我来说,它就像一个看不见的按钮。
Tibidabo

如果您通过self.window?.tintColor = APP_PRIMARY_COLOR在appdelegate中使用此行设置了全局色,则将无法使用
Mehul Thakkar,2015年

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设置为有效。我还设置为启用=否,以防万一...
猪肉小兔子”

3
在iOS7中,将buttonItem.title设置为nil对我不起作用。重新设置该按钮时未出现。但是,所做的工作是设置buttonItem.title = @“”;
Mark Knopper 2013年

42

以下是我的解决方案,尽管我一直在寻找导航栏。

navBar.topItem.rightBarButtonItem = nil;

在这里,“ navBar”是XIB视图中NavigationBar的IBOutlet。在这里,我想隐藏按钮或根据某些条件显示按钮。因此,即时通讯测试条件是否为“ If”,如果为true,则在目标视图的viewDidLoad方法中将按钮设置为nil。

这可能与您的问题不完全相关,但是如果您想隐藏NavigationBar上的按钮,则可能类似


如果以后要rightBarButtonItem再次设置,请确保将按钮项存储在功能强大的 IBOutlet中,以便从导航栏上取下按钮时不会将其释放。
Nate

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
但这仍会占用此按钮的空间。
Makalele '17

22

我目前正在运行针对iOS 7.1的OS X Yosemite Developer Preview 7和Xcode 6 beta 6,以下解决方案对我来说效果很好:

  • 为创建出口UINavigationItemUIBarButtonItem小号
  • 运行以下代码删除

    [self.navItem setRightBarButtonItem:nil];
    [self.navItem setLeftBarButtonItem:nil];
  • 运行以下代码以再次添加按钮

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

谢谢,这也是我发现的最佳方法。只要确保您对按钮的引用牢固即可。
jyoung

另外,请记住,仅当您只有一个按钮时,此方法才有效。该示例将删除该侧的所有按钮。
lnafziger 2015年

@jyoung这对我有用,但是如果引用很强,那为什么重要呢?我没有尝试其他方法,但是通常不是那样设置的,因为它不是默认设置。
罗伯特

@Robert您想在以后使用该对象,因此您需要确保在将其设置为nil时不收集该对象。如果当您告诉bar按钮项目可以删除该对象时,如果没有其他东西可以保留该对象,则该对象的引用计数将为0,并且将被垃圾回收。
jyoung 2015年

14

我在项目中使用了IBOutlets。所以我的解决方案是:

@IBOutlet weak var addBarButton: UIBarButtonItem!

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

当您需要再次显示该栏时,只需设置反向属性即可。

斯威夫特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会为辅助功能启用,并且按钮逻辑隐藏,无障碍光标也将重点放在栏按钮,并指出它是“灰色”(即由于isEnabledIS设置为false)。可接受的答案中的方法没有这种副作用,但是我发现的另一种解决方法是isAccessibilityElement在“隐藏”按钮时将其设置为false:

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

然后isAccessibilityElement在“显示”按钮时将其设置回true:

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

在我的情况下,让bar按钮项仍然占据空间并不是问题,因为我们要隐藏/显示最右边的bar按钮项。


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 18/09/12

4

无法“隐藏” UIBarButtonItem,必须将其从superView中删除,然后在想要再次显示时将其重新添加。


事实并非如此-Max描述的方法效果很好。
北方人

1
nothernman-Max实际上不是正确的。他实际上并没有像大多数人定义“隐藏”那样隐藏按钮。他只是在使其不可见并禁用用户交互。该按钮仍在那里并占用空间。这取决于您要如何定义“隐藏”,我相信原始问题的实质是实际上要删除/添加它,而不仅仅是使其不可见。
Michael Peterson

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 hideToolbarItem(button:UIBarButtonItem,withToolbar工具栏:UINavigationItem){vartoolbarButtons:[UIBarButtonItem] = toolbar.rightBarButtonItems!工具栏按钮.removeAtIndex(工具栏按钮.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 2012年

@lnafziger是的,但是我没有读过关于缩小按钮之间的间距的操作说明,但这是一个值得注意的注意点。
iNoob 2012年

1
谢谢,您的答案也很有用,但是我认为大多数人想要隐藏工具栏上的按钮时,都希望它看起来根本不存在(没有空白区域)。如果是左或右,那实际上并不重要。
lnafziger 2012年

好的要点,iNoob和Inafziger-我都没有提到它,但是是的,我希望没有空白。
萨沙2012年


2

禁用条形按钮项时,将文本颜色设置为纯色可能是一种更干净的选择。您不必在评论中进行解释就很奇怪。同样,您不破坏按钮,因此仍保留所有关联的故事板脚本。

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

然后,无论何时要隐藏条形按钮项,都可以执行以下操作:

self.navigationItem.rightBarButton.enabled = NO;

la脚的是没有隐藏的属性,但这提供了相同的结果。


1
我在rightBarButtonItem内部有一个按钮。因此,我将其启用设置为NO,并将其禁用状态下的映像更改为nil。像魅力一样运作...谢谢
Skywalker 2015年

好主意,但是将图像设置为null对我没有用,我不得不放置一个20x20的透明正方形作为图像
Lena Bru


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

如果您使用的是Swift 3

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

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

作为对Eli Burke的回应的补充,如果您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

您需要操纵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;

0

在IB中,如果将按钮标题留为空白,它将不会出现(从未初始化?)。我希望在UI更新期间的开发过程中经常这样做,如果我希望某个构建的条形按钮项目临时消失而不删除它并丢弃其所有出口引用。

在运行时这不会产生相同的效果,将按钮的标题设置为nil不会导致整个按钮消失。抱歉,实际上并不能回答您的问题,但可能对某些人有用。

编辑:仅当按钮的样式设置为纯色时,此技巧才有效


0

我将在这里添加我的解决方案,因为我在这里找不到它。我有一个动态按钮,其图像取决于一个控件的状态。对我来说,最简单的解决方案是将图像设置nil为不存在该控件。每次控件更新时都会更新图像,因此这对我来说是最佳的。只是为了确保我也将设置enabledNO

在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 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.