iOS 7.1 更新:在此更新中,修改 UINavigationBar 中的 alpha 通道的解决方法似乎已被忽略。现在,最好的解决方案似乎是“处理它”,并希望你选择的任何颜色都能呈现半透明的效果。我仍在寻找解决此问题的方法。
iOS 7.0.3 更新:GitHub library we created 已更新,可在使用 iOS 7.0.3 时略微解决此问题。不幸的是,没有神奇的公式来支持在 iOS 7.0.2 及更早版本和 iOS 7.0.3 中创建的两种颜色。似乎Apple提高了饱和度,但以不透明度为代价(因为模糊的半透明取决于不透明度级别)。我和其他一些人正在努力为此创建一个更好的解决方案。
我相信很多人已经遇到过这样的问题:iOS 7 倾向于降低半透明 UINavigationBar 的颜色饱和度。
我的目标是实现一个具有这种色调但半透明的 UINavigationBar:
https://i.stack.imgur.com/9RjRa.png
但是,通过半透明,我得到了这个。背景视图是白色的,我知道这会使这个视图更亮一点:
https://i.stack.imgur.com/RA5wt.png
有没有办法在保持半透明的同时达到原始颜色?我注意到 Facebook 已经能够让他们的栏变成丰富的蓝色,如下所示:
https://i.stack.imgur.com/C5jXs.png
..所以我知道必须有某种方式。背景视图显然在这里有所作为,但它们的大部分内容也是灰色/白色的。似乎无论您输入哪种条形色调颜色,您都无法在半透明下获得鲜艳的色彩。
更新了解决方案。
这是我最终提出的解决方案。我采用了 aprato 的解决方案,然后将自定义 UINavigationBar
包含在 UINavigationController
子类中。 I have created a repository that has this implementation listed below, along with an example app。
////////////////////////////
// CRNavigationBar.m
////////////////////////////
#import "CRNavigationBar.h"
@interface CRNavigationBar ()
@property (nonatomic, strong) CALayer *colorLayer;
@end
@implementation CRNavigationBar
static CGFloat const kDefaultColorLayerOpacity = 0.5f;
static CGFloat const kSpaceToCoverStatusBars = 20.0f;
- (void)setBarTintColor:(UIColor *)barTintColor {
[super setBarTintColor:barTintColor];
if (self.colorLayer == nil) {
self.colorLayer = [CALayer layer];
self.colorLayer.opacity = kDefaultColorLayerOpacity;
[self.layer addSublayer:self.colorLayer];
}
self.colorLayer.backgroundColor = barTintColor.CGColor;
}
- (void)layoutSubviews {
[super layoutSubviews];
if (self.colorLayer != nil) {
self.colorLayer.frame = CGRectMake(0, 0 - kSpaceToCoverStatusBars, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) + kSpaceToCoverStatusBars);
[self.layer insertSublayer:self.colorLayer atIndex:1];
}
}
@end
////////////////////////////
// CRNavigationController.m
////////////////////////////
#import "CRNavigationController.h"
#import "CRNavigationBar.h"
@interface CRNavigationController ()
@end
@implementation CRNavigationController
- (id)init {
self = [super initWithNavigationBarClass:[CRNavigationBar class] toolbarClass:nil];
if(self) {
// Custom initialization here, if needed.
}
return self;
}
- (id)initWithRootViewController:(UIViewController *)rootViewController {
self = [super initWithNavigationBarClass:[CRNavigationBar class] toolbarClass:nil];
if(self) {
self.viewControllers = @[rootViewController];
}
return self;
}
@end
UINAvigationBar
不是不透明的吗?
UINavigationBar
亮度的解决方案。
iOS 7.0.3 更新:正如你在上面看到的 7.0.3 改变了一些事情。我已经更新了我的要点。希望随着人们的升级,这种情况会消失。
原始答案:我最终得到了一个结合其他两个答案的黑客。我将 UINavigationBar 子类化并在后面添加一个图层,如果各种高度状态栏中的任何一个处于上升状态,则可以使用一些额外的空间来覆盖。图层在布局子视图中进行调整,并且每当您设置 barTintColor 时颜色都会发生变化。
要点:https://gist.github.com/aprato/6631390
setBarTintColor
[super setBarTintColor:barTintColor];
if (self.extraColorLayer == nil) {
self.extraColorLayer = [CALayer layer];
self.extraColorLayer.opacity = self.extraColorLayerOpacity;
[self.layer addSublayer:self.extraColorLayer];
}
self.extraColorLayer.backgroundColor = barTintColor.CGColor;
布局子视图
[super layoutSubviews];
if (self.extraColorLayer != nil) {
[self.extraColorLayer removeFromSuperlayer];
self.extraColorLayer.opacity = self.extraColorLayerOpacity;
[self.layer insertSublayer:self.extraColorLayer atIndex:1];
CGFloat spaceAboveBar = self.frame.origin.y;
self.extraColorLayer.frame = CGRectMake(0, 0 - spaceAboveBar, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) + spaceAboveBar);
}
iOS 7.0 中条形的 tintColor 行为已更改。它不再影响栏的背景,其行为与添加到 UIView 的 tintColor 属性的描述相同。要为栏的背景着色,请使用 -barTintColor。您可以使用以下代码使应用程序同时适用于 ios6 和 ios7。
if(IS_IOS7)
{
self.navigationController.navigationBar.barTintColor = [UIColor blackColor];
self.navigationController.navigationBar.translucent = NO;
}
else
{
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
}
IS_IOS7 是一个宏,在 pch 文件中定义如下。
#define IS_IOS7 ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0)
我没有想出这个解决方案,但它似乎工作得很好。我刚刚将它添加到 UINavigationController 子类的 viewDidLoad 中。
来源:https://gist.github.com/alanzeino/6619253
// cheers to @stroughtonsmith for helping out with this one
UIColor *barColour = [UIColor colorWithRed:0.13f green:0.14f blue:0.15f alpha:1.00f];
UIView *colourView = [[UIView alloc] initWithFrame:CGRectMake(0.f, -20.f, 320.f, 64.f)];
colourView.opaque = NO;
colourView.alpha = .7f;
colourView.backgroundColor = barColour;
self.navigationBar.barTintColor = barColour;
[self.navigationBar.layer insertSublayer:colourView.layer atIndex:1];
colourView
的 alpha。我分叉了另一个答案,并将一些东西固定到一个新的临时课程中:github.com/alanzeino/AZColoredNavigationBar
一种低保真方式可能是将作为导航栏高度的 UIView
固定到导航栏后面的视图顶部。使该视图与导航栏颜色相同,但使用 alpha 直到获得所需的效果:
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.navigationController.navigationBar.frame), 64)];
backgroundView.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:1 alpha:.5];
[self.navigationController.view insertSubview:backgroundView belowSubview:self.navigationController.navigationBar];
UIView 后面
https://i.stack.imgur.com/c3CMI.png
(将颜色从较低的示例更改为强调透明度。透明度/模糊在移动时更加明显。)
将 UINavigationBar
子类化并将相同的视图放在背景上方但在其他所有内容之后可能会获得类似的结果,同时不那么 hacky。
我见过的另一个解决方案是使用
UINavigationBar
的 alpha:
self.navigationController.navigationBar.alpha = 0.5f;
编辑:实际上,经过测试,这似乎没有提供预期的行为(或任何行为):
.8 阿尔法
https://i.stack.imgur.com/nMhLz.png
未调整的阿尔法
https://i.stack.imgur.com/rorI0.png
显然,您只想在 iOS 7 设备上执行此操作。因此,在您实施其中任何一项之前,add some version check。
[self.navigationController.view insertSubview:backgroundView belowSubview:self.navigationController.navigationBar];
不要以 RGB 格式创建 UIColor 对象,而是使用 HSB 并增加饱和度参数。 (归功于描述此方法 here 的 Sam Soffes)
navigationBar.barTintColor = [UIColor colorWithHue:0.555f saturation:1.f brightness:0.855f alpha:1.f];
注意:此解决方案是一种折衷方案,不适用于高饱和度的颜色。
要从您的设计中选择 HSB 颜色,您可以使用像 ColorSnapper 这样的工具,它允许您简单地复制 UIColor HSB 格式。
您还可以尝试使用 David Keegan 中的 UIColor 类别 (GitHub Link) 来修改现有颜色。
Apple 已在新的 7.0.3 版本中修复了该问题。
我使用了@aprato 的解决方案,但发现了一些极端情况,其中来自新 VC 的新层(例如 UINavigationItemButtonViews
、UINavigationItemViews
等)会自动插入到 extraColorLayer
下方的位置(这会导致这些标题或按钮元素会受到 extraColorLayer
的影响,因此颜色比正常情况要暗)。所以我调整了@aprato 的解决方案,强制 extraColorLayer
保持在索引位置 1。在索引位置 1,extraColorLayer
保持在 _UINavigationBarBackground
的正上方,但在其他所有位置的下方。
这是我的类实现:
- (void)setBarTintColor:(UIColor *)barTintColor
{
[super setBarTintColor:barTintColor];
if (self.extraColorLayer == nil)
{
self.extraColorLayer = [CALayer layer];
self.extraColorLayer.opacity = kDefaultColorLayerOpacity;
[self.layer insertSublayer:self.extraColorLayer atIndex:1]; // This way the text comes out clear
}
self.extraColorLayer.backgroundColor = barTintColor.CGColor;
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (self.extraColorLayer != nil)
{
self.extraColorLayer.frame = CGRectMake(0, 0 - kSpaceToCoverStatusBars, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) + kSpaceToCoverStatusBars);
}
}
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview
{
[super insertSubview:view aboveSubview:siblingSubview];
[self.extraColorLayer removeFromSuperlayer];
[self.layer insertSublayer:self.extraColorLayer atIndex:1]; // This way the text comes out clear
}
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index
{
[super insertSubview:view atIndex:index];
[self.extraColorLayer removeFromSuperlayer];
[self.layer insertSublayer:self.extraColorLayer atIndex:1]; // This way the text comes out clear
}
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview
{
[super insertSubview:view belowSubview:siblingSubview];
[self.extraColorLayer removeFromSuperlayer];
[self.layer insertSublayer:self.extraColorLayer atIndex:1]; // This way the text comes out clear
}
我在我的 fork 中改进了您的代码:https://github.com/allenhsu/CRNavigationController
通过我的修改,屏幕上的结果颜色(在白色背景上选取)将与传递给 setBarTintColor
的值完全相同。我认为这是一个了不起的解决方案。
这些黑客都不是必需的:)。简单设置:
self.navigationController.navigationBar.translucent = NO;
对于 iOS 7,默认的半透明保持为 TRUE。
在相关说明中,您可以通过以下方式轻松设置标题文本颜色(带阴影):
NSShadow *titleShadow = [[NSShadow alloc] init];
titleShadow.shadowOffset = CGSizeMake(0.0f, -1.0f);
titleShadow.shadowColor = [UIColor blackColor];
NSDictionary *navbarTitleTextAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor],
NSShadowAttributeName: titleShadow};
[[UINavigationBar appearance] setTitleTextAttributes:navbarTitleTextAttributes];
我在尝试设置一个统一颜色的导航栏时遇到了这个 Q/A,在 iOS 7 上禁用了透明度。
在用 barTintColor 试验了一段时间后,我发现拥有不透明导航栏的一种非常简单的方法是制作所需颜色的单像素图像,从中制作可拉伸的图像,并将其设置为导航栏的背景图像.
UIImage *singlePixelImage = [UIImage imageNamed:@"singlePixel.png"];
UIImage *resizableImage = [singlePixelImage resizableImageWithCapInsets:UIEdgeInsetsZero];
[navigationBar setBackgroundImage:resizableImage forBarMetrics:UIBarMetricsDefault];
三行代码,非常简单,适用于 iOS 6 和 iOS 7(iOS 6 不支持 barTintColor)。
GitHub Here GitHub - C360NavigationBar 上的 Simon Booth 提供了一个很棒的 Dropin UINavigationController 替代品
如果您向后支持 iOS6,请检查根视图控制器,如下所示:
PatientListTableViewController *frontViewController = [[PatientListTableViewController alloc] init];
UINavigationController *navViewController = [[UINavigationController alloc] initWithNavigationBarClass:[C360NavigationBar class] toolbarClass:nil];
if ([navViewController.view respondsToSelector:@selector(setTintColor:)]) {
//iOS7
[navViewController.view setTintColor:self.navBarTintColor];
[[C360NavigationBar appearance] setItemTintColor:self.navBarItemTintColor];
} else {
//iOS6
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:NO];
navViewController.navigationBar.tintColor = self.navBarTintColor;
}
[navViewController pushViewController:frontViewController animated:NO];
self.window.rootViewController = navViewController;
作为@bernhard mentioned above,可以使条形颜色饱和以获得所需的导航栏外观。
我为这种调整写了一个BarTintColorOptimizer utility。它优化了半透明条的色调颜色,使条的实际颜色与 iOS 7.x 及更高版本中所需的颜色相匹配。查看 this answer 了解详情。
坦率地说,以上答案可能是正确的,但以下技巧对我来说很容易。
// this is complete 100% transparent image
self.imageBlack = [[UIImage imageNamed:@"0102_BlackNavBG"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 2, 0, 2)
resizingMode:UIImageResizingModeStretch];
// this is non-transparent but iOS7
// will by default make it transparent (if translucent is set to YES)
self.imageRed = [[UIImage imageNamed:@"0102_RedNavBG"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 2, 0, 2)
resizingMode:UIImageResizingModeStretch];
// some navigation controller
[nvCtrLeft.navigationBar setBackgroundImage:self.imageRed
forBarMetrics:UIBarMetricsDefault];
// some another navigation controller
[nvCtrCenter.navigationBar setBackgroundImage:self.imageRed
forBarMetrics:UIBarMetricsDefault];
以下是用于 self.imageRed
和 self.imageBlack
的图像。
https://i.stack.imgur.com/EFhlm.png
https://i.stack.imgur.com/rlgmu.png
有没有办法在不继承 UINavigationBar 的情况下使用 @aprato 解决方案。
在我的项目中,我的主视图是 UIViewController。
问题是navigationController是一个只读属性,有没有办法在我的项目中使用你的类,因为我不能使用:[[UINavigationController alloc] initWithNavigationBarClass:
谢谢
UIViewController
包装在带有 [[[UINavigationController alloc] initWithRootViewController:<YourViewController>]
的 UINavigationController
中吗?这也可能作为一个单独的问题得到更好的回答,而不是在此处发布。
获得所需颜色的一种简单方法是使用
[<NAVIGATION_BAR> setBackgroundImage:<UIIMAGE> forBarPosition:<UIBARPOSITION> barMetrics:<UIBARMETRICS>];
只要您的图像有一些 alpha,半透明就会起作用,您可以通过更改图像来设置 alpha。这只是在 iOS7 中添加的。图像的宽度和高度是垂直的 640x88 像素(如果您希望它位于状态栏下方,则将 20 添加到 88)。
UINavigationController
子类中。对于那些有兴趣在UINavigationController
中包含自定义UINavigationBar
的人来说,这是其中的 gist。initWithRootViewController
以使用它。我已经更新了我的要点