iOS 7の半透明のUINavigationBarで明るく鮮やかな色を実現する


172

iOS 7.1のアップデート:UINavigationBarのアルファチャネルを変更するための回避策は、このアップデートでは無視されているようです。現在のところ、最善の解決策は、「それに対処する」ことであり、選択した色が半透明の効果をレンダリングできることを期待しているようです。私はまだこれを回避する方法を調べています。


iOS 7.0.3のアップデート作成したGitHubライブラリは、iOS 7.0.3を使用するときにこの問題を少し回避するようにアップデートされました。残念ながら、iOS 7.0.2以前とiOS 7.0.3で作成された両方の色をサポートする魔法の公式はありません。Appleは彩度を改善したようですが、不透明度が犠牲になります(ぼやけた半透明度は不透明度レベルに依存するため)。私は、他の数人と一緒に、これに対するより良い修正の作成に取り組んでいます。


iOS 7が半透明のUINavigationBarの色の彩度を下げる傾向があるという問題にすでに多くの人が遭遇していると思います。

私の目標は、この色合いで半透明のUINavigationBarを実現することです。

UINavigationBar、不透明

しかし、半透明で、私はこれを得ています。背景ビューは白ですが、このビューは少し明るくなると思います。

UINavigationBar、Translucent

半透明性を維持しながら元の色を実現する方法はありますか?ここに表示されているように、Facebookがバーを豊かな青色にできることに気づきました。

Facebook UINavigationBar、Translucent

..だから何か方法があるはずだと知っています。ここで背景ビューは明らかに違いをもたらしますが、そのコンテンツのほとんどは灰色/白です。どんなバーティントカラーを入れても、半透明では鮮やかな色が出ないようです。

ソリューションで更新されました。

これが私が思いついた解決策です。私は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

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

Facebook iOS7はUINAvigationBar不透明ではありませんか?
Vinzzz

いいえ、それはデフォルトのiOSよりもはるかに微妙な透明度です。はるかに良い、IMO。
ケビン

Facebook NavigationBarは透明ではありません
LE SANG

7
それは間違いなく半透明です。私の編集した応答をご覧ください。
SpacePyro 2013

2
@Odelya -これは正しい色を得るための解決策ではなく、明度補正する溶液UINavigationBarのiOS 7に半透明にさらされたときに可能な限り最良の
SpacePyro

回答:


52

iOS 7.0.3 UPDATE:上記の7.0.3のように変更されました。要点を更新しました。うまくいけば、これは人々がアップグレードするのと同時になくなるでしょう。

元の回答: 私は他の2つの回答を組み合わせたハックに終わりました。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;

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);
  }

これをViewControllerのどこに実装しましたか?viewDidLoadの下で?
ジェレミー

これは美しく機能します!これをUINavigationControllerサブクラスに追加することにしました。これは、内にカスタムを持つことに興味がある人のための要点です。UINavigationBarUINavigationController
SpacePyro 2013

SpacePyroのような@Jeremy私はinitWithRootViewControllerこれを使用するためにオーバーライドするナビゲーションコントローラサブクラス(UIAppearanceターゲティングに7以前のバージョンを使用していたバーのように)を持っています。要点を更新しました
アンソニー

ええと…大丈夫です。私は、あなたが何を意味するのかを完全に理解するために、テストプロジェクト全体でこれを見る必要があると思います。以下のタイムユーザーの例を複製することができましたが、これはまだ少しグリーンです。
ジェレミー

1
@ Mr.Tありがとう!私が書いたときはまだプッシュされていませんでした:)しかし、私は今それを更新し、不透明度のためのUIAppearanceとNSCodingのサポートを追加しました
Anthony

10

バーのtintColorの動作がiOS 7.0で変更されました。これはバーの背景に影響しなくなり、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)

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];

1
新しいビューコントローラーをナビゲーションコントローラーにプッシュした後、バーボタンの項目がこの透明レイヤーの下に移動するように見えます。
エヴァン・デイビス

タイトルもこの透明レイヤーによって不明瞭になります。
Nick Locking

この要旨を書いた。コメントは正しいです。新しいビューコントローラーが押されると、ボタンアイテムが下に押されるか、サブレイヤーがのアルファを継承しcolourViewます。私は他の答えを分岐して、いくつかのことを新しいドロップインクラスに修正しました
Alan Zeino 2013

Translucent Black Navigation Barスタイルを選択することで、テキストを白くすることができました...これでうまくいきました。yourBar.tintColor = [UIColor whiteColor]も設定します。上部の他のカスタムボタンの場合。
ファンサモラ

6

1つのローファイな方法は、おそらくUIViewナビゲーションバーの高さをバーの後ろのビューの上部に固定することです。そのビューをナビゲーションバーと同じ色にしますが、目的の効果が得られるまでアルファを操作します。

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

ここに画像の説明を入力してください

(下の例から透明度を強調するように色を変更しました。移動中は透明度/ぼやけがより目立ちます。)

をサブクラス化し、UINavigationBar同じビューを背景の上に配置しますが、他のすべての背後に配置すると、ハックが少なく、おそらく同じような結果が得られます。


私が見た別の解決策は、のアルファで遊ぶことUINavigationBarです:

self.navigationController.navigationBar.alpha = 0.5f;

編集:実際には、テスト後、これは意図した動作(または任意の動作)を提供しないようです:

.8アルファ

.8 alphaのナビゲーションバー

未調整アルファ

ここに画像の説明を入力してください

明らかに、これはiOS 7デバイスでのみ実行する必要があります。したがって、これらのいずれかを実装する前に、いくつかのバージョンチェックを追加してください


次に、アルファとtintColorを更新して、探している色を取得する方法を紹介します。
StuartM 2013

あなたがそのより侵襲性の少ない方法で望ましい効果を得ることができるなら、完全に。しかし、それがどれほど効果的かはわかりません。
ケビン

私がこれで得ている唯一の問題(そしてそれはあなたの写真に表されていないようです)は、それがナビゲーションバーの上に直接ビューを追加することであり、その結果、コントロールがブロックされます:cl.ly / image / 3d3C2o0N283S
SpacePyro

おっと、今はわかります。する必要があります[self.navigationController.view insertSubview:backgroundView belowSubview:self.navigationController.navigationBar];
ケビン

ええ、私はそれがあなたの意味するところだと考えました。;)これは間違いなく私が選ぶ色のより良いスパンを与えます。元の色の鮮やかさを取得することは、ぼかし効果がまだその下にあるものを本当に彩度を下げることを考えるとおそらく不可能でしょう。とりあえず、もっと暗い色で暮らす必要があります。
SpacePyro 2013

4

RGB形式でUIColorオブジェクトを作成する代わりに、HSBを使用して彩度パラメーターを増やします。(ここでこの方法を説明するSam Soffesへのクレジット)

navigationBar.barTintColor = [UIColor colorWithHue:0.555f saturation:1.f brightness:0.855f alpha:1.f];

注:このソリューションはトレードオフであり、彩度の高い色ではうまく機能しません。

デザインからHSBカラーを選択するには、ColorSnapperなどのツールを使用できます。などの、UIColor HSB形式を簡単にコピーできます。

UIColorカテゴリー(David Keegan GitHub Link)を既存の色を変更するます。


3

この問題は、新しい7.0.3リリースでAppleによって修正されました。


1
はい、その色合いの実装は7.0.3で間違いなく変更されました。彩度を約10〜15%上げるだけで、目的の色を実現できます。以前は、追加のレイヤーもアドする必要がありました。
Matej Bukovinski 2013年

知らせてくれてありがとうございます!私はこのために私のライブラリに更新をプッシュします。
SpacePyro 2013年

1
7.1で未修正> _ <
Leo Natan

1

私は、新しいベンチャーキャピタルからの新しい層が(例えば、いくつかのコーナーケースapratoのソリューション@使用されたが見つからUINavigationItemButtonViewsUINavigationItemViewsなど)を自動的に下の位置に挿入されるだろう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
}

レイヤーとサブビューが混在していないため、addSubViewをオーバーロードする必要はありません
Rob van der Veer

1

私のフォークのコードを改善しました:https : //github.com/allenhsu/CRNavigationController

私の変更により、画面上の結果の色(白い背景で選択)は、に渡される値とまったく同じになりますsetBarTintColor。素晴らしいソリューションだと思います。


@JordanBrownは7.1および8ではテストされていません
Allen Hsu

0

これらのハックは必要ありません:) 単に設定する:

self.navigationController.navigationBar.translucent = NO;

iOS 7の場合、デフォルトの半透明度はTRUEに維持されています。


17
しかし、問題には透明性も必要です。
レオナタン

:)ありがとう、それは私のために働いた。ただし、ナビゲーションバーの下に1pxの黒い下枠があります。それを削除する方法はありますか?
Pritesh Desai 2013

0

関連するノートでは、タイトルテキストの色(影付き)を次の方法で簡単に設定できます

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];

1
iOS 7のスタイルに合わせる場合は、タイトルテキストにドロップシャドウを使用するのはおそらく不適切です。
Nick Locking 2013

正解です。iOS7では、Appleはナビゲーションバーのテキストに影を設定しなくなりました。ただし、カスタムの外観が必要な場合は、これによりオプションが提供されます。
bryguy1300 2013

0

iOS 7で透明度が無効になっている均一な色のナビゲーションバーをセットアップしようとしているときに、このQ / Aに遭遇しました。

barTintColorをしばらく試した後、不透明なナビゲーションバーを作成する非常に簡単な方法は、目的の色の単一ピクセルイメージを作成し、それから伸縮可能なイメージを作成して、ナビゲーションバーのbackgroundImageに設定することです。 。

UIImage *singlePixelImage = [UIImage imageNamed:@"singlePixel.png"];
UIImage *resizableImage = [singlePixelImage resizableImageWithCapInsets:UIEdgeInsetsZero];
[navigationBar setBackgroundImage:resizableImage forBarMetrics:UIBarMetricsDefault]; 

3行のコード。非常にシンプルで、iOS 6とiOS 7の両方で機能します(barTintColorはiOS 6ではサポートされていません)。


0

ここGitHubで入手可能なサイモンブースから入手可能な素晴らしいDropin UINavigationControllerの代替品があります 。GitHub-C360NavigationBar

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;

私が何かを見逃していない限り、このライブラリのバーは半透明ではありません。
Rivera

0

上記の@bernhardで説明したように、バーのティントカラーを飽和させて、目的のナビゲーションバーの外観を得ることができます。

そのような調整のために、BarTintColorOptimizerユーティリティを作成しました。透明なバーの色合いの色を最適化して、バーの実際の色をiOS 7.x以降の目的の色に一致させます。詳細については、この回答をご覧ください。


-1

率直に言って、上記の答えは正しいかもしれませんが、次のトリックは非常に簡単に私のために働きました。

// 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.imageRedself.imageBlackです。

< self.imageBlack >このブラケット内の黒い画像は透明であるため表示されません:)

< self.imageRed>赤い画像はこの括弧内にあります。


これはあなたにぼかしを与えません。
Ortwin Gentz

-1

UINavigationBarをサブクラス化せずに@apratoソリューションを使用する方法はありますか。

私のプロジェクトでは、メインビューはUIViewControllerです。

問題は、navigationControllerが読み取り専用プロパティであることです。使用できないため、プロジェクトでクラスを使用する方法はありますか。 [[UINavigationController alloc] initWithNavigationBarClass:

ありがとう


あなたは自分のラップできませんでしたUIViewController内部AをUINavigationControllerして[[[UINavigationController alloc] initWithRootViewController:<YourViewController>]?これは、ここに投稿するのではなく、別の質問として回答した方がよい場合もあります。
SpacePyro 2013

-2

希望の色を取得する簡単な方法は、

    [<NAVIGATION_BAR> setBackgroundImage:<UIIMAGE> forBarPosition:<UIBARPOSITION> barMetrics:<UIBARMETRICS>];

画像にアルファが含まれている限り、半透明が機能し、画像を変更することでアルファを設定できます。これはiOS7で追加されたばかりです。画像の幅と高さは、垂直方向で640x88pxです(ステータスバーの下に表示する場合は、88に20を追加します)。


ただし、ぼかしは保持されません。透明感はありますが、にじみはありません。
レオナタン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.