Ottenere colori brillanti e vivaci per una UINavigationBar traslucida iOS 7


172

AGGIORNAMENTO iOS 7.1 : sembra che la soluzione alternativa per la modifica del canale alfa in UINavigationBar sia stata ignorata in questo aggiornamento. In questo momento, la soluzione migliore sembra essere quella di "affrontarlo" e sperare che qualunque colore scegliate possa rendere un effetto traslucido. Sto ancora cercando modi per aggirare questo.


AGGIORNAMENTO di iOS 7.0.3 : la libreria GitHub che abbiamo creato è stata aggiornata per aggirare leggermente questo problema quando si utilizza iOS 7.0.3. Sfortunatamente, non esiste una formula magica per supportare entrambi i colori creati in iOS 7.0.2 e precedenti e iOS 7.0.3. Sembra che Apple abbia migliorato la saturazione, ma a costo dell'opacità (poiché la traslucenza sfocata dipende dal livello di opacità). Io, insieme ad alcuni altri, sto lavorando per creare una soluzione molto migliore per questo.


Sono sicuro che molte persone hanno già riscontrato il problema in cui iOS 7 tende a desaturare il colore di una UINavigationBar che è traslucida.

Il mio obiettivo è quello di ottenere un UINavigationBar con questo colore di tinta, ma traslucido:

UINavigationBar, Opaque

Tuttavia, con traslucenza, sto ottenendo questo. La vista di sfondo è bianca, che capisco renderà questa vista un po 'più chiara:

UINavigationBar, Translucent

Esiste un modo per ottenere il colore originale pur avendo la traslucenza? Ho notato che Facebook è stato in grado di far diventare la loro barra il loro ricco colore blu, come mostrato qui:

Facebook UINavigationBar, Translucent

.. so che deve esserci un modo. Le viste di sfondo ovviamente fanno la differenza qui, ma la maggior parte del loro contenuto è anche grigio / bianco. Sembra che, indipendentemente dal colore della tinta della barra che inserisci, non puoi ottenere colori vivaci sotto la traslucenza.

Aggiornato con soluzione.

Ecco la soluzione che mi è venuta in mente. Ho preso la soluzione di Aprato e poi ho incluso l'abitudine UINavigationBarin una UINavigationControllersottoclasse. Ho creato un repository che ha questa implementazione elencata di seguito, insieme a un'app di esempio .

////////////////////////////
// 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 non è UINAvigationBaropaco?
Vinzzz,

No, è una trasparenza molto più sottile di quella predefinita di iOS. Molto meglio, IMO.
Kevin,

Navigazione FacebookBar non trasparente
LE SANG

7
È decisamente traslucido; per favore vedi la mia risposta modificata.
SpacePyro,

2
@Odelya - Questa non è una soluzione per ottenere i colori corretti, ma piuttosto una soluzione per correggere la leggerezza del UINavigationBarmeglio possibile quando esposto alla traslucenza in iOS 7.
SpacePyro

Risposte:


52

AGGIORNAMENTO di iOS 7.0.3: come vedi sopra 7.0.3 le cose sono cambiate. Ho aggiornato il mio succo. Spero che questo scompaia man mano che le persone aggiornano.

Risposta originale: ho finito con un trucco che combina le due delle altre risposte. Sto subclassando UINavigationBar e aggiungendo un livello sul retro con un po 'di spazio in più da coprire se una delle varie barre di stato dell'altezza è sollevata. Il livello viene regolato nelle visualizzazioni secondarie del layout e il colore cambia ogni volta che si imposta barTintColor.

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

Dove lo hai implementato su ViewController? Sotto viewDidLoad?
Jeremy,

Funziona magnificamente! Ho deciso di aggiungere questo alla mia UINavigationControllersottoclasse. Ecco un riassunto per coloro che sono interessati ad avere un'abitudine UINavigationBarall'interno di un UINavigationController.
SpacePyro,

@Jeremy come SpacePyro Ho una sottoclasse del controller di navigazione (che come la barra che stavo usando pre 7 per il targeting di UIApearance) che sostituisce initWithRootViewControllerper usare questo. Ho aggiornato la mia idea
Anthony,

Ehm ... okay ... Penso di aver bisogno di vederlo in un intero progetto di test per vedere appieno cosa intendi. Sono stato in grado di replicare l'esempio di timeuser qui sotto, ma sono ancora un po 'verde con questo.
Jeremy,

1
@ Mr.T Grazie! Quando ho scritto che non stava ancora spingendo :) Ma l'ho aggiornato ora, ho aggiunto UIApearance per l'opacità e il supporto per NSCoding
Anthony,

10

Il comportamento di tintColor per le barre è cambiato su iOS 7.0. Non influisce più sullo sfondo della barra e si comporta come descritto per la proprietà tintColor aggiunta a UIView. Per tingere lo sfondo della barra, si prega di utilizzare -barTintColor. È possibile utilizzare il codice seguente per far funzionare l'app con iOS6 e iOS7.

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

IS_IOS7 è una macro definita nel file pch come segue.

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

9

Non ho trovato questa soluzione ma sembra funzionare abbastanza bene. L'ho appena aggiunto a viewDidLoad nella mia sottoclasse di UINavigationController.

Fonte: 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
Sembra che dopo aver spinto un nuovo View Controller sul controller di navigazione, tutti gli elementi dei pulsanti della barra vengano spostati in questo livello di trasparenza.
Evan Davis,

Anche i titoli vengono oscurati da questo livello di trasparenza.
Nick Locking,

Ho scritto questo riassunto. I commenti sono giusti; entrambi gli elementi dei pulsanti vengono spinti sotto quando viene premuto un nuovo controller di visualizzazione o i sublayer ereditano l'alfa di colourView. Ho riposto l'altra risposta e sistemato alcune cose in una nuova classe drop-in: github.com/alanzeino/AZColoredNavigationBar
Alan Zeino

Sono stato in grado di mettere il testo in bianco selezionando lo stile della barra di navigazione nera traslucida ... questo ha fatto il trucco per me. Imposta anche yourBar.tintColor = [UIColor whiteColor]; per altri pulsanti personalizzati in alto.
Juan Zamora,

6

Un modo low-fi sarebbe probabilmente quello di fissare UIViewun'altezza della barra di navigazione nella parte superiore della vista dietro la barra. Rendi la vista dello stesso colore della barra di navigazione ma gioca con l'alfa fino ad ottenere gli effetti desiderati:

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 dietro

inserisci qui la descrizione dell'immagine

(Cambiato colore dagli esempi inferiori per enfatizzare la trasparenza. Trasparenza / sfocatura è più evidente quando in movimento.)

Sottoclassare UINavigationBare posizionare la stessa vista sopra lo sfondo ma dietro tutto il resto probabilmente otterrà risultati simili pur essendo meno confuso.


Un'altra soluzione che ho visto lanciata è giocare con l'alfa di UINavigationBar:

self.navigationController.navigationBar.alpha = 0.5f;

Modifica: In realtà, dopo il test sembra che questo non fornisca il comportamento previsto (o alcun comportamento):

.8 alfa

Barra di navigazione con .8 alfa

Alfa non aggiustata

inserisci qui la descrizione dell'immagine

Ovviamente, vorrai farlo solo su dispositivi iOS 7. Quindi, aggiungi qualche controllo di versione prima di implementare uno di questi.


In secondo luogo l'approccio di aggiornamento di alpha e tintColor per ottenere il colore che stai cercando.
StuartM,

Se riesci a ottenere gli effetti desiderati con quel modo meno invasivo, allora totalmente. Ma non sono sicuro di quanto sarà efficace.
Kevin,

L'unico problema che sto riscontrando con questo (e non sembra rappresentato nella tua immagine) è che sta aggiungendo la vista direttamente sulla barra di navigazione e, di conseguenza, sta causando il blocco dei controlli: cl.ly / image / 3d3C2o0N283S
SpacePyro

Spiacenti, ora vedo. Dovrebbe essere[self.navigationController.view insertSubview:backgroundView belowSubview:self.navigationController.navigationBar];
Kevin,

Sì, ho pensato che fosse quello che intendevi. ;) Questo mi dà sicuramente una migliore gamma di colori tra cui scegliere. Ottenere la vibrazione del colore originale sarà probabilmente impossibile se si considera che l'effetto sfocatura continua a desaturare qualsiasi cosa sotto di esso. Dovrò solo vivere con un colore più scuro per ora.
SpacePyro,

4

Invece di creare il tuo oggetto UIColor nel formato RGB , usa HSB e aumenta il parametro di saturazione. (Crediti a Sam Soffes che descrive questo metodo qui )

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

Nota: questa soluzione è un compromesso e non funziona bene per i colori con elevata saturazione.

Per scegliere il colore HSB dal tuo disegno puoi usare uno strumento simile ColorSnapper che ti consente semplicemente di copiare il formato UIColor HSB.

Puoi anche provare la categoria UIColor ( GitHub Link ) di David Keegan per modificare i colori esistenti.


3

Il problema è stato risolto da Apple nella nuova versione 7.0.3.


1
Sì, la loro implementazione del colore della tinta è decisamente cambiata in 7.0.3. Ora posso ottenere il colore desiderato semplicemente aumentando la saturazione di circa il 10-15%. Prima avevo anche bisogno di aggiungere il livello aggiuntivo.
Matej Bukovinski,

Grazie per avermi fatto sapere! A tale scopo, invierò un aggiornamento alla mia libreria.
SpacePyro,

1
E non risolto in 7.1> _ <
Leo Natan,

1

Ho usato la soluzione di @ aprato, ma ho trovato alcuni casi angolari in cui i nuovi livelli di nuovi VC (ad es. UINavigationItemButtonViews, Ecc. UINavigationItemViews) Sarebbero stati automaticamente inseriti in una posizione al di sotto del extraColorLayer(il che causerebbe la modifica di tali elementi del titolo o del pulsante extraColorLayere quindi di colore più debole di quello che sarebbero normalmente). Quindi ho modificato la soluzione di @ aprato per forzare il mantenimento della extraColorLayerposizione dell'indice 1. Alla posizione dell'indice 1, il valore extraColorLayerrimane sopra il_UINavigationBarBackground , ma sotto tutto il resto.

Ecco la mia implementazione di classe:

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

Poiché i livelli e le visualizzazioni secondarie non sono misti, non è necessario sovraccaricare addSubView
Rob van der Veer,


0

Nessuno di questi hack è richiesto :). Basta impostare:

self.navigationController.navigationBar.translucent = NO;

Per iOS 7, la traslucenza predefinita è stata mantenuta su TRUE.


17
Ma la domanda richiede anche traslucenza.
Leo Natan,

:) Grazie, ha funzionato per me. Tuttavia c'è un bordo inferiore nero 1px sotto la barra di navigazione. C'è un modo per rimuoverlo?
Pritesh Desai,

0

In una nota correlata, puoi impostare facilmente il colore del testo del titolo (con ombra) tramite:

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
Se stai cercando di abbinare lo stile di iOS 7, probabilmente è inappropriato usare un'ombra sul testo del titolo.
Nick Locking,

Hai ragione, in iOS 7 Apple non imposta più le ombre sul testo della barra di navigazione. Se volessi un look personalizzato, questo ti darebbe l'opzione.
bryguy1300,

0

Mi sono imbattuto in questo Q / A durante il tentativo di impostare una barra di navigazione di colore uniforme con trasparenza DISATTIVATA su iOS 7.

Dopo aver sperimentato un po 'con barTintColor ho capito che un modo molto semplice di avere una barra di navigazione opaca è quello di creare un'immagine a pixel singolo del colore desiderato, crearne un'immagine estensibile e impostarla sullo sfondo. Immagine della barra di navigazione .

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

Tre righe di codice, molto semplici e funzionano ENTRAMBI su iOS 6 e iOS 7 (barTintColor non è supportato su iOS 6).


0

C'è un'ottima sostituzione Dropin UINavigationController disponibile da Simon Booth disponibile su GitHub qui GitHub - C360NavigationBar

Se stai supportando all'indietro iOS6, verifica come tale il controller di root:

PatientListTableViewController * frontViewController = [[Allocazione PatientListTableViewController] 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;

A meno che non mi manchi qualcosa, le barre di questa biblioteca non sono traslucide.
Rivera,


-1

Francamente parlando, le risposte sopra potrebbero essere giuste, ma il trucco seguente ha funzionato per me con molta facilità.

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

Ecco le immagini utilizzate per self.imageRede self.imageBlack.

< self.imageBlack> l'immagine nera tra parentesi non sarà visibile poiché è trasparente :)

L' self.imageRedimmagine rossa è tra queste parentesi.


Questo non ti dà sfocatura.
Ortwin Gentz,

-1

c'è un modo per usare la soluzione @aprato senza sottoclassare UINavigationBar.

Nel mio progetto la mia vista principale è un UIViewController.

il problema è che navigationController è una proprietà di sola lettura, c'è un modo per usare la tua classe con il mio progetto perché non posso usare: [[UINavigationController alloc] initWithNavigationBarClass:

Grazie


Non potresti semplicemente avvolgere il tuo UIViewControllerinterno UINavigationControllercon [[[UINavigationController alloc] initWithRootViewController:<YourViewController>]? Potrebbe anche essere meglio rispondere a questa domanda come una domanda separata, piuttosto che pubblicare qui.
SpacePyro,

-2

Un modo semplice per ottenere il colore desiderato è l'utilizzo

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

Finché la tua immagine ha un po 'di alfa, la traslucenza funzionerà e puoi impostare l'alfa cambiando l'immagine. Questo è stato appena aggiunto in iOS7. La larghezza e l'altezza dell'immagine sono 640x88 px per la verticale (aggiungere 20 all'88 se si desidera che si trovi sotto la barra di stato).


Tuttavia, ciò non mantiene la sfocatura. C'è trasparenza, ma non sfocatura.
Leo Natan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.