为iOS 7半透明UINavigationBar实现明亮鲜艳的色彩

Spa*_*yro 172 objective-c uinavigationbar uikit ios ios7


iOS 7.1更新:在此更新中,似乎忽略了修改UINavigationBar中Alpha通道的变通方法.现在,最好的解决方案似乎只是"处理它",并希望你选择的任何颜色都可以呈现半透明效果.我仍然在寻找解决这个问题的方法.


iOS 7.0.3更新:使用iOS 7.0.3时,我们创建GitHub库已经更新,可以解决此问题.不幸的是,没有神奇的公式可以支持iOS 7.0.2及更早版本和iOS 7.0.3中创建的颜色.似乎Apple改善了饱和度,但是以不透明度为代价(因为模糊的半透明度取决于不透明度水平).我和其他一些人正在努力为此创建更好的解决方案.


我相信很多人已经遇到过这样的问题:iOS 7倾向于使半透明的UINavigationBar的颜色饱和.

我的目标是使用这种色调实现UINavigationBar,但是半透明:

UINavigationBar,Opaque

然而,有了半透明,我得到了这个.背景视图是白色的,据我所知会使这个视图更轻一些:

UINavigationBar,半透明

有没有办法在保持半透明的同时达到原色?我注意到Facebook已经能够让他们的酒吧变成他们丰富的蓝色,如下所示:

Facebook UINavigationBar,半透明

..所以我知道必须有某种方式.背景视图在这里显然有所不同,但其大部分内容也是灰色/白色.似乎无论你放入什么样的色调,你都无法在半透明的情况下获得鲜艳的色彩.

更新了解决方案.

这是我最终提出的解决方案.我采用了aprato的解决方案,然后UINavigationBarUINavigationController子类中包含了自定义.我创建了一个具有下面列出的实现的存储库,以及一个示例应用程序.

////////////////////////////
// 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
Run Code Online (Sandbox Code Playgroud)
////////////////////////////
// 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
Run Code Online (Sandbox Code Playgroud)

Ant*_*ony 52

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;
Run Code Online (Sandbox Code Playgroud)

layoutSubviews

  [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);
  }
Run Code Online (Sandbox Code Playgroud)


Bha*_*esh 10

在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];
}
Run Code Online (Sandbox Code Playgroud)

IS_IOS7是一个宏,它在pch文件中定义如下.

#define IS_IOS7 ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0)
Run Code Online (Sandbox Code Playgroud)


Jam*_*ick 9

我没有提出这个解决方案,但似乎工作得相当好.我刚刚将它添加到我的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];
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 6

一种低保真方式可能会将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];
Run Code Online (Sandbox Code Playgroud)

UIView背后

在此输入图像描述

(将颜色从较低的示例更改为强调透明度.移动时透明度/模糊更明显.)

UINavigationBar同一视图进行子类化并将其置于背景之上但落后于其他所有视图可能会获得类似的结果,同时不那么黑客.


我见过的另一种解决方案是使用以下方法UINavigationBar:

self.navigationController.navigationBar.alpha = 0.5f;
Run Code Online (Sandbox Code Playgroud)

编辑:实际上,在测试后,它似乎没有提供打算行为(或任何行为):

.8 alpha

带有.8 alpha的导航栏

未经调整的阿尔法

在此输入图像描述

显然,您只想在iOS 7设备上执行此操作.因此,在实现任何这些之前添加一些版本检查.