iOS 7:禁用整个应用程序的 UINavigationBar 半透明

Posted

技术标签:

【中文标题】iOS 7:禁用整个应用程序的 UINavigationBar 半透明【英文标题】:iOS 7 : Disable UINavigationBar Translucency For Entire App 【发布时间】:2013-09-18 22:19:10 【问题描述】:

有没有办法为整个应用程序禁用 UINavigationBar 半透明?

我知道使用[self.navigationController.navigationBar setTranslucent:NO] 可以解决单个控制器的这个问题,但是我的应用程序中有很多 UINavigationBars,这是一个非常乏味的解决方案。

我试过[[UINavigationBar appearance] setTranslucent:NO],但令人惊讶的是不支持该功能。这样做会导致Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** Illegal property type, c for appearance setter, _installAppearanceSwizzlesForSetter:'

如果我必须这样做,我可以通过我的整个应用程序设置 UINavigationBars 来逐个禁用半透明,但必须有一些更优雅的解决方案来解决这个问题......

【问题讨论】:

你在使用故事板吗? 很遗憾,我不是。 更好的是,有没有办法强制我的视图以理智的方式布局而不需要关闭半透明?这太荒谬了 【参考方案1】:

如果您将堆栈中第一个导航栏的半透明设置为false[self.navigationController.navigationBar setTranslucent:NO],它将反映在推送到该堆栈的所有以下 NavigationViewController 中。

【讨论】:

如果您使用情节提要,请从 UINavigationController 中取消选择透明度。 如果您显示任何模态视图控制器或导航控制器中未出现的任何内容,则此解决方案不完整。【参考方案2】:

如果您想将此样式应用于整个应用程序,这里有一个 Swift 解决方案。

AppDelegate 类中将其添加到didFinishLaunchingWithOptions

对于 Swift 2:

UINavigationBar.appearance().translucent = false

对于 Swift 3+:

UINavigationBar.appearance().isTranslucent = false

【讨论】:

【参考方案3】:

appDelegatedidFinishLaunchingWithOptions 中的这段代码看起来很简单(适用于 ios 8 及更高版本)

[[UINavigationBar appearance] setTranslucent:NO];

【讨论】:

我不知道为什么有人给了这个负分,我用了这个并且工作得很好!我投了赞成票! 绝对有可能!还是谢谢。【参考方案4】:

我认为您对没有可用于此属性的外观代理是正确的。您使用的是 UINavigationControllers 还是 UINavigationBar 对象?如果您使用 UINavigationBars,您可以对其进行子类化并创建一个非半透明导航栏。

头文件:

#import <UIKit/UIKit.h>

@interface ABCNonTranslucentNavBar : UINavigationBar

@end

实现文件:

#import "ABCNonTranslucentNavBar.h"

@implementation ABCNonTranslucentNavBar

- (void)drawRect:(CGRect)rect

  [self setTranslucent:NO];

然后只需将 UINavigationBars 替换为您的子类。您也可以对子类 UINavigationController 执行类似操作。

【讨论】:

这绝对是一个有趣的想法,但有点痛苦。也许有更简单的方法......?不管现在这个问题的答案如何,如果 iOS 7.1 没有添加半透明外观代理,我会感到震惊。另外,为了回答您的问题,我使用的是 UINavigationControllers,而不仅仅是栏。 使用方法 swizzle 并在 viewDidLoad 上打补丁怎么样? 你也可以继承 UINavigationController 并重写指定的初始化器来设置 self.navigationBar.translucent = NO 这样做是 -drawRect:... 看你的应用程序崩溃了 ;)【参考方案5】:

添加此内容以防有人仍在与此作斗争。

你可以通过指定一个不存在的图像来欺骗它,这将使导航栏包括它的工具栏变得不透明

[[UIToolbar appearance] setBackgroundColor:[UIColor colorWithRed:219.0/255.0 green:67.0/255.0 blue:67.0/255.0 alpha:1.0]];

[[UIToolbar appearance] setBackgroundImage:[[UIImage alloc] init] forToolbarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];

【讨论】:

当把它应用到 uinavigationbar 时,你会得到一个黑色的状态栏 :(【参考方案6】:

我知道这是旧的,但这可能对某人有用;

您可以使用一个类别,并在其中*设置属性[translucent][1]

@implementation UINavigationBar (MakeTranslucent)

-(void)willMoveToWindow:(UIWindow *)newWindow 
    [super willMoveToWindow:newWindow];


    self.translucent = NO;

@end
我用过willMoveToWindow,不知道UAYOR这样是不是个好主意。

【讨论】:

请注意,这是危险的,因为它不会调用 willMoveToWindow: 的原始 UINavigationBar 实现。 category 方法完全替换了该方法的原始实现,因此您实际上是跳过了原始 UINavigationBar 实现并直接调用 UIView 的实现。 ***.com/questions/6168058/… 使用类别覆盖方法是个糟糕的主意。事实上,在 iOS 8.3 中,覆盖类方法的类方法似乎不会被调用。【参考方案7】:

参见 UIKit 代码文档的摘录:

/*
     New behavior on iOS 7.
     Default is YES.
     You may force an opaque background by setting the property to NO.
     If the navigation bar has a custom background image, the default is inferred 
     from the alpha values of the image—YES if it has any pixel with alpha < 1.0
     If you send setTranslucent:YES to a bar with an opaque custom background image
     it will apply a system opacity less than 1.0 to the image.
     If you send setTranslucent:NO to a bar with a translucent custom background image
     it will provide an opaque background for the image using the bar's barTintColor if defined, or black
     for UIBarStyleBlack or white for UIBarStyleDefault if barTintColor is nil.
     */

正确的 Swift 4 解决方案是

UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().backgroundColor = .white

【讨论】:

【参考方案8】:

我认为外观 api 不支持导航栏的半透明属性。 但是你可以像这样对整个 App 执行此操作,请看一下这段代码 --

这里的 Menu Screen 是一个根视图控制器。

MenuScreen *ms = [[MenuScreen alloc]initWithNibName:@"MenuScreen" bundle:nil];

UINavigationController *nv = [[UINavigationController alloc]initWithRootViewController:ms];

//This will set property for whole App.
[nv.navigationBar setTranslucent:NO];

self.window.rootViewController = nv ;

【讨论】:

它只会为这一导航堆栈设置为半透明。如果您有任何模态导航控制器、多个选项卡或任何其他类型的更复杂的导航模式,则将无法正常工作。 所以你必须像这样设置每个堆栈 是的,当然。但这个问题的重点是,是否有一种方法可以全局 设置它(比如通过UIAppearance),而这正是你正在做的。此外,您在回答中说“将为整个应用程序设置”,这是不正确的。【参考方案9】:

如果您不使用故事板,而是使用 IB,请将 MainWindows.xib 的导航栏样式设置为 NOT translucent,并设置为颜色而不是清晰的颜色。

【讨论】:

以上是关于iOS 7:禁用整个应用程序的 UINavigationBar 半透明的主要内容,如果未能解决你的问题,请参考以下文章

UIBarButtonItem 在 ios6 中看起来很糟糕

如何在 iOS 7 App 中禁用 iCloud

是否可以在 iOS 7 上从我的应用程序中禁用推送通知声音?

如何在 iOS 7/8 的单个视图上禁用横向

如何在 iOS 7 上的 UINavigationController 中禁用向后滑动手势

在 iOS 7 中更改后退按钮会禁用滑动导航