如何显示/隐藏UIBarButtonItem?

274

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

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


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

10

我发现在Max和其他人建议的tintColorisEnabled方法中又有了一个小问题——当开启辅助功能的VoiceOver并且逻辑上隐藏了该按钮时,辅助功能光标仍会聚焦于该条形按钮,并且说明它是“已禁用”(因为isEnabled被设为假)。被采纳的答案中的方法不会出现这种副作用,但我找到的另一个解决方法是当“隐藏”该按钮时将isAccessibilityElement设为假:

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

当“显示”按钮时,将isAccessibilityElement重新设置为true:

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

在我的情况下,保留标准按钮项的空间并不是问题,因为我们隐藏/显示了最左边或最右边的按钮项。


9

如果您在 Swift 中使用 UIBarButtonItem 并且在 AppDelegate 中设置了一些设计相关的属性,比如字体大小,请不要更新 tintColor,因为这会完全改变按钮显示时的外观。

对于文本按钮,更改标题可能会导致按钮“消失”。

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

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

6
@IBDesignable class AttributedBarButtonItem: UIBarButtonItem {

    var isHidden: Bool = false {

        didSet {

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

现在只需更改isHidden属性即可。


5

改进自@lnafziger的答案

将您的Barbuttons保存在一个强大的outlet中,然后执行以下操作以隐藏/显示它:

-(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
这是在答案列表中找到的较为靠后的一个,但如果有人想要一个简单的复制粘贴的解决方案,这里就是它:

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 toolbar: UINavigationItem) { var toolbarButtons: [UIBarButtonItem] = toolbar.rightBarButtonItems! toolbarButtons.removeAtIndex(toolbarButtons.indexOf(button)!) toolbar.setRightBarButtonItems(toolbarButtons, animated: true) }这样就可以正常工作了。 - Kingalione

4

无法“隐藏”UIBarButtonItem,您必须将其从superView中删除,并在需要显示它时将其添加回去。


这实际上是不正确的 - Max所描述的方法很有效。 - northernman
1
nothernman - Max 实际上并不正确。他并没有以大多数人定义的“隐藏”方式来隐藏该按钮。他只是使其不可见并禁用用户交互。该按钮仍然存在并占据空间。这取决于您如何定义“隐藏”,我认为原始问题的精神是想要实际删除/添加它,而不仅仅是使其不可见。 - Michael Peterson

3
一种方法是使用initWithCustomView:(UIView *)属性分配UIBarButtonItemUIView的子类将具有隐藏/显示属性。
例如: 1. 有一个您想要隐藏/显示的UIButton2.UIButton作为自定义视图。例如:
UIButton*myButton=[UIButton buttonWithType:UIButtonTypeRoundedRect];//your button

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

3. 您可以隐藏/显示您创建的myButton[myButton setHidden:YES];

Translated: "3. 您可以隐藏/显示您创建的 myButton。[myButton setHidden:YES];"

然而,它不会关闭其他按钮之间的间隙:当它被“隐藏”时,工具栏上会有一个空白区域。 - lnafziger
@lnafziger 是的,那是真的,但我没有看到 OP 提到缩小按钮之间的间隙,不过这是一个值得注意的好点。 - iNoob
1
谢谢,你的回答也很有用,但我认为大多数人想要隐藏工具栏上的按钮时,希望它看起来就像根本不存在一样(没有空白区域)。如果是左边或右边的按钮,那倒无所谓。 - lnafziger
好的观点,iNoob和Inafziger - 我没有明确说明,但是是的,我希望不要有空白处。 - Sasha

3

最终,从开始,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
        }
    }
}

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