小编典典

为 iOS 7 半透明 UINavigationBar 实现明亮、生动的色彩

all

iOS 7.1 更新:在此更新中,修改 UINavigationBar 中的 alpha 通道的解决方法似乎已被忽略。现在,最好的解决方案似乎是“处理它”,并希望你选择的任何颜色都能呈现半透明的效果。我仍在寻找解决此问题的方法。


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


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

我的目标是实现一个具有这种色调但半透明的 UINavigationBar:

UINavigationBar,不透明

但是,通过半透明,我得到了这个。背景视图是白色的,我知道这会使这个视图更亮一点:

UINavigationBar,半透明

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

Facebook UINavigationBar,半透明

..所以我知道必须有某种方式。背景视图显然在这里有所作为,但它们的大部分内容也是灰色/白色的。似乎无论您输入哪种条形色调颜色,您都无法在半透明下获得鲜艳的色彩。

更新了解决方案。

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

////////////////////////////
// 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

阅读 114

收藏
2022-08-29

共1个答案

小编典典

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);
  }
2022-08-29