如何显示/隐藏UIBarButtonItem?

274

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

UIBarButtonItem没有隐藏属性,目前我找到的任何关于隐藏它们的示例都涉及将导航栏按钮设置为nil,在这里我认为不需要这样做,因为我可能需要再次显示按钮(更不用说,如果我将我的按钮连接到IBOutlet,如果我将其设置为nil,我不确定如何重新获取它)。


我只是将其禁用,并添加了一个辅助功能标签,说明该按钮的功能不可用。 - user5306470
39个回答

271

将你的按钮保存在一个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];
}

因为它存储在插座中,所以即使它不在工具栏上,你仍将保留对它的引用。


75
为了使导航控制器中我的右侧按钮起作用,我使用了self.navigationItem.rightBarButtonItems和[self.navigationItem setRightBarButtonItems<prams>],而不是toolBarItems和setToolBarItems。 - MindSpiker
1
@MindSpiker:是的,同样的技巧也适用于导航栏上的按钮。 - lnafziger
1
在dealloc中我需要将myButton设置为nil吗? - Van Du Tran

227

我知道这个答案对于这个问题来说有些晚了,但如果其他人面临类似情况可能会有所帮助。

在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]];[self.navigationItem.rightBarButtonItem setEnabled:NO]; [self.navigationItem.rightBarButtonItem setTintColor:[UIColor clearColor]]; - Leon
5
对于 Swift:使用 deleteButton.enabled = false; deleteButton.tintColor = UIColor.clearColor() 来禁用并隐藏按钮,使用 deleteButton.enabled = true; deleteButton.tintColor = nil 来重新启用并正常显示。 - Unixmonkey
1
我喜欢这种方法,因为它让我可以将是否显示UIBarButton的逻辑放在该类中。它只适用于一个按钮的原因并不是立即显而易见的——因为如果你以这种方式隐藏一个按钮,它仍然会占用空间,所以如果你有多个按钮,你可能会有一个空的间隙。 - SimplGy
你的第一种方法对我来说非常完美。我为UIControlState.disabled设置了UIColor.clear,并可以使用setEnabled显示/隐藏按钮。当然,正如你所说,这仅适用于文本按钮。 - heyfrank
如果长按它直到它弹出一个大图像(可能是为了辅助功能),那么即使将isEnabled设置为false,它仍然可以工作。 - user5306470

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
1
对我不起作用。我以为是因为我使用了带有“+”图像的添加按钮,但我尝试了一个自定义按钮,上面写着“新建”,但它仍然没有消失。启用更改,所以我知道我的代码正在执行。有什么想法吗?请注意,此按钮是在故事板中创建的,并具有segue,因此我不想改为编程按钮。 - Rhubarb
23
似乎在导航控制器的工具栏中它不起作用,但在其他工具栏中可以。 - Drew Rosenberg
3
它虽然隐藏了,但仍会对轻触作出反应。对我来说它就像是一个隐形按钮。 - Tibidabo
如果您在appdelegate中使用此行代码self.window?.tintColor = APP_PRIMARY_COLOR设置了全局的色调颜色,则这将不起作用。 - Mehul Thakkar

62

可以在不改变按钮宽度或从栏中删除按钮的情况下隐藏按钮。如果将样式设置为plain,删除标题并禁用按钮,则按钮会消失。要恢复它,只需撤销更改即可。

-(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。我还设置了enabled = NO,以防万一... - Pork 'n' Bunny
3
在iOS7中,将buttonItem.title设置为nil对我没有起作用。当将其设置回来时,按钮没有重新出现。然而,有效的方法是将buttonItem.title设置为@" "。 - Mark Knopper

44

以下是我的解决方案,虽然我是在寻找导航栏的解决方案时发现的。

navBar.topItem.rightBarButtonItem = nil;

这里,“navBar”是连接到XIB视图中NavigationBar的IBOutlet。我想根据某些条件隐藏或显示按钮。因此,我在“if”中测试了该条件,并且如果为真,则将按钮设置为nil并在目标视图的viewDidLoad方法中执行。

这可能与您的问题不完全相关,但如果您想隐藏NavigationBar上的按钮,可以参考类似的方法。


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

36

对于 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使用的原始颜色。

3
但是这仍然会占用该按钮的空间。 - Makalele

22

我目前正在运行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];
    

1
谢谢,这也是我找到的最好的方法。只要确保你对按钮的引用很强。 - jyoung
1
另外,请记住,这仅适用于您那边只有一个按钮的情况。该示例将删除该侧的所有按钮。 - lnafziger
@jyoung 这对我有用,但为什么引用是强引用很重要呢?我没有尝试过另一种方式,但通常不会这样设置,因为它不是默认值。 - Robert
1
@Robert 你想在以后使用这个对象,所以你需要确保当你将其设置为nil时,该对象不会被垃圾回收。如果没有其他东西在你告诉工具栏按钮项可以摆脱它时保留该对象,它的引用计数将为0,然后它将被垃圾回收。 - jyoung

14

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

@IBOutlet weak var addBarButton: UIBarButtonItem!

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

当需要再次显示此栏时,只需设置反转属性即可。

Swift 3 中,使用 isEnable 属性而不是 enable


13

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

意思是将self.dismissButton的customView属性设置为一个新建的UIView对象,并且该对象的frame属性被设置为CGRectMake(0, 0, 0, 0)。

12

iOS 8. 自定义图像的UIBarButtonItem。 尝试了许多不同的方法,大多数都没有帮助。 Max的解决方案,setTintColor没有改变任何颜色。 我自己想出了这个方法,认为对某些人有用。

隐藏:

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

展示用途:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接