İOS 7 yarı saydam UINavigationBar için parlak, canlı renkler elde etme


172

iOS 7.1 GÜNCELLEME : Görünüşe göre, bu güncellemede UINavigationBar'daki alfa kanalını değiştirmek için geçici çözüm yok sayıldı. Şu anda, en iyi çözüm sadece 'onunla başa çıkmak' ve seçtiğiniz rengin yarı saydam bir etki yaratabileceğini ummak gibi görünüyor. Hala bunun üstesinden gelmenin yollarını arıyorum.


iOS 7.0.3 GÜNCELLEME : Oluşturduğumuz GitHub kütüphanesi , iOS 7.0.3 kullanılırken bu soruna geçici bir çözüm bulmak için güncellendi. Ne yazık ki, iOS 7.0.2 ve önceki sürümlerde ve iOS 7.0.3'te oluşturulan her iki rengi de destekleyen sihirli bir formül yoktur. Apple doygunluğu geliştirdi, ancak opaklık pahasına görünüyor (bulanık saydamlık opaklık seviyesine bağlı olduğundan). Birkaç kişi ile birlikte bunun için çok daha iyi bir düzeltme yaratmaya çalışıyorum.


Pek çok insanın iOS 7'nin yarı saydam bir UINavigationBar rengini desatura etme eğiliminde olduğu sorunuyla zaten karşılaştığına eminim.

Amacım, bu renk tonu rengiyle ancak yarı saydam bir UINavigationBar elde etmek:

UINavigationBar, Opak

Ancak, yarı saydamlıkla, bunu alıyorum. Arka plan görünümü beyaz, bu görünümü biraz daha hafif hale getireceğimizi anlıyorum:

UINavigationBar, Yarı Saydam

Yarı saydamlığı korurken orijinal rengi elde etmenin herhangi bir yolu var mı? Facebook'un barının burada gösterildiği gibi zengin, mavi rengi olmasını sağlayabildiğini fark ettim:

Facebook UINavigationBar, Yarı Saydam

.. yani bir şekilde olması gerektiğini biliyorum. Arka plan görünümleri burada bir fark yaratır, ancak içeriklerinin çoğu da gri / beyazdır. Görünüşe göre, hangi bar renk tonunu koyarsanız koyun, yarı saydamlık altında canlı renkler elde edemezsiniz.

Çözüm ile güncellendi.

İşte sonunda bulduğum çözüm. Çektiğim aprato özel kapsayan ardından 'ın çözüm ve UINavigationBarbir içinde UINavigationControlleralt sınıf. Örnek bir uygulama ile birlikte, bu uygulama aşağıda listelenen bir havuz oluşturduk .

////////////////////////////
// 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 UINAvigationBaropak değil mi?
Vinzzz

Hayır, varsayılan iOS'tan çok daha ince bir şeffaflık. Çok daha iyi, IMO.
Kevin

Şeffaf değil
LE SANG

7
Kesinlikle yarı saydamdır; lütfen düzenlenen yanıtımı görün.
SpacePyro

2
@Odelya - Bu, doğru renkleri elde etmek için bir çözüm değil, daha ziyade UINavigationBariOS 7'de yarı saydamlığa maruz kaldığında mümkün olan en iyi parlaklığını düzeltmek için bir çözümdür .
SpacePyro

Yanıtlar:


52

iOS 7.0.3 GÜNCELLEME: Yukarıdaki 7.0.3'te gördüğünüz gibi şeyler değişti. Özümü güncelledim. Umarım bu insanlar yükselttikçe ortadan kaybolacaktır.

Orijinal Cevap: Diğer cevapların ikisini birleştiren bir hack ile sonuçlandım. UINavigationBar alt sınıflandırma ve çeşitli yükseklik durum çubukları herhangi biri varsa kapsayacak bazı ekstra alan ile arka katman ekliyorum. Katman, düzen alt görünümlerinde ayarlanır ve barTintColor'u her ayarladığınızda renk değişir.

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

Bunu ViewController'da nereye uyguladınız? ViewDidLoad altında mı?
Jeremy

Bu güzel çalışıyor! Bunu UINavigationControlleralt sınıfıma eklemeye karar verdim . İşte bu özü özel bir sahip ilgilenen olanlar için bunun UINavigationBarbir mesafede UINavigationController.
SpacePyro

@ SpacePyro gibi Jeremy Bunu kullanmak için geçersiz kılan bir nav denetleyicisi alt sınıfına (UIApearance hedeflemesi için 7 öncesi kullandığım çubuk gibi) sahibim initWithRootViewController. Özümü güncelledim
Anthony

Um ... tamam ... Ne demek istediğini tam olarak görmek için bunu bir test projesinde görmem gerekiyor. Zamanlayıcı örneğini aşağıdaki gibi kopyalayabildim ama yine de bununla biraz yeşilim.
Jeremy

1
@ Mr.T Teşekkürler! Ben henüz itme değildi yazarken :) Ama şimdi güncelledim, NSCoding için opaklık ve destek için UIApearance ekledi
Anthony

10

İOS 7.0'da çubuklar için tintColor'un davranışı değişti. Artık çubuğun arka planını etkilemez ve UIView'a eklenen tintColor özelliği için açıklandığı şekilde davranır. Çubuğun arka planını renklendirmek için lütfen -barTintColor kullanın. Uygulamanın hem ios6 hem de ios7 ile çalışmasını sağlamak için aşağıdaki kodu kullanabilirsiniz.

if(IS_IOS7)
{
    self.navigationController.navigationBar.barTintColor = [UIColor blackColor];
    self.navigationController.navigationBar.translucent = NO;
}
else
{
    self.navigationController.navigationBar.tintColor = [UIColor blackColor];
}

IS_IOS7, pch dosyasında aşağıdaki gibi tanımlanan bir makrodur.

#define IS_IOS7 ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0)

9

Bu çözümü bulamadım ama gayet iyi çalışıyor gibi görünüyor. Sadece UINavigationController alt sınıfımda viewDidLoad için ekledi.

Kaynak: 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
Yeni bir Görünüm Denetleyicisini Gezinti denetleyicisine ittikten sonra, herhangi bir çubuk düğmesi öğesi bu saydamlık katmanının altına taşınacak gibi görünüyor.
Evan Davis

Başlıklar da bu saydamlık katmanı tarafından gizleniyor.
Nick Locking

Bu özeti yazdım. Yorumlar doğrudur; yeni bir görünüm denetleyicisine basıldığında düğme öğelerinin altına itilir veya alt katmanlar alfa'nın mirasını alır colourView. Diğer cevabı çatalladım
Alan Zeino

Yarı Saydam Siyah Gezinme Çubuğu stilini seçerek metni beyazlaştırabildim ... bu benim için hile yaptı. Ayrıca yourBar.tintColor = [UIColor whiteColor] ayarını yapın; üstteki diğer özel düğmeler için.
Juan Zamora

6

Düşük frekanslı yollardan biri, muhtemelen UIViewGezinti Çubuğu'nun yüksekliğinin, çubuğun arkasındaki görünümün üst kısmına sabitlenmesidir . Bu görünümü gezinme çubuğuyla aynı renkte yapın, ancak istediğiniz efektleri elde edene kadar alfa ile oynayın:

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

Arkasında UIView

resim açıklamasını buraya girin

(Renk daha düşük örneklerden vurgu saydamlığına dönüştürüldü. Şeffaflık / bulanıklaştırma hareket halindeyken daha belirgindir.)

UINavigationBarAynı görünümü alt sınıflara ayırmak ve arkaplanın üstüne koymak, ancak her şeyin arkasına yerleştirmek muhtemelen daha az hileli olurken benzer sonuçlar elde edecektir.


Etrafında savunduğum başka bir çözüm, alfa ile oynamaktır UINavigationBar:

self.navigationController.navigationBar.alpha = 0.5f;

Düzenleme: Aslında, test ettikten sonra bu niyet davranışı (veya herhangi bir davranış) sağlamaz gibi görünüyor:

.8 alfa

.8 alfa içeren gezinti çubuğu

Düzeltilmemiş alfa

resim açıklamasını buraya girin

Açıkçası, bunu yalnızca iOS 7 cihazlarında yapmak isteyeceksiniz. Bu nedenle, bunlardan herhangi birini uygulamadan önce bir sürüm kontrolü ekleyin .


İkinci olarak, aradığınız rengi elde etmek için alfa ve tintColor'ı güncelleme yaklaşımı.
StuartM

İstediğiniz efektleri daha az invaziv bir şekilde elde ederseniz, o zaman tamamen. Ama ne kadar etkili olacağından emin değilim.
Kevin

Bununla ilgili aldığım tek sorun (ve resminizde temsil edilmiyor gibi görünüyor) görünümü doğrudan gezinme çubuğunun üstüne eklemesi ve bunun sonucunda kontrollerin engellenmesine neden olmasıdır: cl.ly / image / 3d3C2o0N283S
SpacePyro

Hata! Şimdi anlıyorum. Olmalı[self.navigationController.view insertSubview:backgroundView belowSubview:self.navigationController.navigationBar];
Kevin

Evet, ne demek istediğini anladım. ;) Bu kesinlikle bana seçim için daha iyi bir renk aralığı verir. Orijinal rengin canlılığını elde etmek, bulanıklık efektinin hala altındaki her şeyi gerçekten desaturate ettiğini düşünerek muhtemelen imkansız olacaktır. Şimdilik sadece daha koyu bir renkle yaşamam gerekecek.
SpacePyro

4

UIColor nesnenizi RGB formatında oluşturmak yerine HSB kullanın ve doygunluk parametresini artırın. ( Bu yöntemi burada açıklayan Sam Soffes'e verilen krediler )

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

Not: Bu çözüm bir ödünleşmedir ve yüksek doygunluğa sahip renkler için iyi çalışmaz.

HSB rengini tasarımınızdan seçmek için ColorSnapper gibi bir araç kullanabilirsiniz , UIColor HSB formatını kopyalamanıza izin veren .

Mevcut renkleri değiştirmek için David Keegan'ın UIColor Kategorisini ( GitHub Bağlantısı ) da deneyebilirsiniz .


3

Sorun, yeni 7.0.3 sürümünde Apple tarafından düzeltildi.


1
Evet, renk tonu uygulamaları 7.0.3'te kesinlikle değişti. Artık doygunluğum yaklaşık% 10-15 oranında artırarak istediğim rengi elde edebilirim. Daha önce fazladan katmanı da eklemem gerekti.
Matej Bukovinski

Bilmeme izin verdiğin için teşekkürler! Bunun için kütüphaneme bir güncelleme göndereceğim.
SpacePyro

1
Ve 7.1> _ <
Leo Natan

1

Yeni VC yeni tabakalar (örneğin., Bir kaç köşe durumlarda aprato çözeltisi @ kullanılan ancak bulunan UINavigationItemButtonViews, UINavigationItemViewsvs.) otomatik olarak alttan bir konuma sokulur; extraColorLayerbu, başlık veya düğme elemanları etkilenebilir neden olur ( extraColorLayerve dolayısıyla normalde olduğundan daha renkli olur). Bu yüzden @ aprato'nun çözümünü extraColorLayer, indeks konumu 1'de kalmaya zorlamak için ayarladım . İndeks konumu 1'de, extraColorLayerhemen _UINavigationBarBackgroundher şeyin altında, ancak altında kalır .

İşte benim sınıf uygulaması:

- (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
}

Katmanlar ve alt görünümler karışık olmadığından, aşırı yüklenen addSubView gerekli değil
Rob van der Veer


0

Bu saldırıların hiçbiri gerekli değildir :). Basitçe ayarlayın:

self.navigationController.navigationBar.translucent = NO;

İOS 7 için varsayılan yarı saydamlık DOĞRU olarak tutulmuştur.


17
Ancak soru da yarı saydamlık gerektirir.
Leo Natan

:) Teşekkürler, benim için çalıştı. Ancak gezinme çubuğunun altında 1 piksel siyah bir alt kenarlık var. Kaldırmanın herhangi bir yolu var mı?
Pritesh Desai

0

İlgili bir notta, başlık metni renginizi (gölgeli) aşağıdakileri kullanarak kolayca ayarlayabilirsiniz:

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
İOS 7'nin stilini eşleştirmeye çalışıyorsanız, başlık metninizde alt gölge kullanmak muhtemelen uygun değildir.
Nick Kilitleme

Doğru, iOS 7'de Apple artık navbar metninde gölgeler ayarlamıyor. Yine de özel bir görünüm istiyorsanız, bu size seçenek sunacaktır.
bryguy1300

0

İOS 7'de saydam OLMAYAN şeffaflık içeren düzgün renkli bir gezinme çubuğu oluşturmaya çalışırken bu Q / A ile karşılaştım.

BarTintColor ile bir süre denedikten sonra, opak bir gezinme çubuğuna sahip olmanın çok kolay bir yolunun, istenen rengin tek bir piksel görüntüsünü yapmak, dışarıya gerilebilir bir görüntü yapmak ve arka plana ayarlamak olduğunu anladım. .

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

Üç satır kod, çok basit ve iOS 6 ve iOS 7'de İKİ çalışıyor (barTintColor, iOS 6'da desteklenmiyor).


0

GitHub'da bulunan Simon Booth'tan harika bir Dropin UINavigationController değişimi var GitHub - C360NavigationBar

İOS6'yı geriye doğru destekliyorsanız, kök görünüm denetleyicisini aşağıdaki gibi kontrol edin:

PatientListTableViewController * frontViewController = [[PatientListTableViewController ayır] 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;

Bir şey eksik olmadıkça, bu kütüphanenin çubukları yarı saydam değildir.
Rivera


-1

Açıkçası, yukarıdaki cevaplar doğru olabilir ama takip hilesi benim için çok kolay çalıştı.

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

İşte için kullanılan görüntülerdir self.imageRedve self.imageBlack.

< self.imageBlack > siyah görüntü bu köşeli ayraç şeffaf olduğu için görünmez :)

< self.imageRed> kırmızı görüntü bu köşeli parantezler içinde.


Bu size bulanıklık vermez.
Ortwin Gentz

-1

@aprato çözümünü UINavigationBar alt sınıflaması olmadan kullanmanın bir yolu var.

Projemde ana görüşüm UIViewController.

Sorun şu ki, kullanamam çünkü navigationController salt okunur bir özellik, benim proje ile sınıf kullanmak için bir yol var: [[UINavigationController alloc] initWithNavigationBarClass:

Teşekkürler


Eğer sadece sarın Could UIViewControlleriç a UINavigationControllerile [[[UINavigationController alloc] initWithRootViewController:<YourViewController>]? Bu, burada yayınlamak yerine ayrı bir soru olarak daha iyi cevaplanabilir.
SpacePyro

-2

İstediğiniz rengi elde etmenin kolay bir yolu kullanmaktır

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

Görüntünüzde bazı alfa olduğu sürece, yarı saydamlık çalışır ve görüntüyü değiştirerek alfa ayarlayabilirsiniz. Bu sadece iOS7'de eklendi. Görüntünün genişliği ve yüksekliği dikey için 640x88 pikseldir (durum çubuğunun altında olmasını istiyorsanız 88'e 20 ekleyin).


Ancak bu bulanıklığı korumaz. Şeffaflık var, ama bulanıklık yok.
Leo Natan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.