如何显示/隐藏UIBarButtonItem?

274

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

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


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

0

为了隐藏多个项目中的一个,我使用了以下代码:

self.navigationItem.leftBarButtonItems?.remove(at: 0)  
self.navigationItem.rightBarButtonItems?.remove(at: 1)

如果需要,我想这些项目可以被重新添加。


0

子类化 UIBarButtonItem。 确保在 Interface Builder 中将按钮设置为 HidableBarButtonItem。 从按钮到视图控制器创建一个 outlet。然后可以通过调用 setHidden: 在视图控制器中隐藏/显示按钮。

HidableBarButtonItem.h

#import <UIKit/UIKit.h>

@interface HidableBarButtonItem : UIBarButtonItem

@property (nonatomic) BOOL hidden;

@end

HidableBarButtonItem.m

#import "HidableBarButtonItem.h"

@implementation HidableBarButtonItem

- (void)setHidden:(BOOL const)hidden {
    _hidden = hidden;

    self.enabled = hidden ? YES : NO;
    self.tintColor = hidden ? [UIApplication sharedApplication].keyWindow.tintColor : [UIColor clearColor];
}

@end

0

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

将宽度设置为最小值在iOS 7上不起作用。


0

在 IB 中,如果您将按钮的标题留空,则不会显示(从未初始化?)。在 UI 更新期间,在开发过程中经常这样做,如果我想让一个栏按钮项在构建时暂时消失而不删除它并丢弃所有其输出引用。

在运行时,这没有相同的效果,将按钮的标题设置为 nil 不会导致整个按钮消失。抱歉并没有真正回答你的问题,但可能对一些人有用。

编辑:此技巧仅适用于将按钮样式设置为 plain 的情况


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

0

我遇到了一个问题,即我有两个leftBarButtonItems。在Mac Catalyst上,firstButton指向的操作不受支持:使用AVFoundation录制视频。只有第二个按钮在Mac Catalyst上是有效的:使用UIImagePickerController。

因此,在Mac Catalyst上,我必须将第一个UIBarButtonItem指向secondButton,并始终隐藏第二个UIBarButtonItem。在iOS上,应显示两个按钮。这是我的解决方案:

#if TARGET_OS_MACCATALYST
        self.navigationItem.leftBarButtonItem = self.secondButton;
        NSUInteger count = [self.navigationItem.leftBarButtonItems count];
        for (NSUInteger i = 0; i < count; i++) {
            UIBarButtonItem *thisButton = [self.navigationItem.leftBarButtonItems objectAtIndex:i];
            if (i == 1) {
                thisButton.enabled = NO;
                thisButton.tintColor = [UIColor clearColor];
            }
        }
#else
        self.navigationItem.leftBarButtonItem = self.firstButton;
#endif

我希望它能帮助到有类似问题的人。


0

参考 @haste的答案

extension UIBarButtonItem {
    var isHidden: Bool {
        set {
            if #available(iOS 16.0, *) {
                isHidden = newValue
            } else {
                isEnabled = !newValue
                tintColor = newValue ? .clear : nil
            }
        }
        
        get {
            if #available(iOS 16.0, *) {
                return isHidden
            } else {
                return isEnabled == false && tintColor == .clear
            }
        }
    }
}

-1

我的答案适用于Swift 4!

if $0 {
    self.navigationItem.rightBarButtonItems = [UIBarButtonItem(customView: self.button1)]
} else {
    self.navigationItem.rightBarButtonItems = [UIBarButtonItem(customView: self.button2)]
}

-5
我的解决方案是将bounds.width设置为0,用于UIBarButtonItem中的内容(我在UIButton和UISearchBar中使用了这种方法):
隐藏:
self.btnXXX.bounds = CGRectMake(0,0,0,0);

显示:

self.btnXXX.bounds = CGRectMake(0,0,40,30); // <-- put your sizes here

它实际上适用于iOS 6及以下版本,但现在不再适用。 - Mike Keskinov

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