Osiągnięcie jasnych, żywych kolorów dla przezroczystego paska UINavigationBar iOS 7


IOS 7.1 UPDATE: wygląda na to, że obejście zmiany kanału alfa w pasku UINavigationBar zostało zignorowane w tej aktualizacji. W tej chwili najlepszym rozwiązaniem wydaje się po prostu "radzić sobie z tym" i mieć nadzieję, że dowolny kolor, który wybierzesz, przyniesie półprzezroczysty efekt. Wciąż szukam sposobów na obejście tego.


IOS 7.0.3 UPDATE: biblioteka GitHub, którą stworzyliśmy została zaktualizowana, aby nieco obejść ten problem problem podczas korzystania z iOS 7.0.3. Niestety, nie ma magicznej formuły obsługującej oba kolory utworzone w iOS 7.0.2 i wcześniejszych oraz iOS 7.0.3. Wydaje się, że Apple poprawiło nasycenie, ale kosztem nieprzezroczystości (ponieważ rozmyta przezroczystość zależy od poziomu nieprzezroczystości). Ja, wraz z kilkoma innymi, pracuję nad stworzeniem znacznie lepszej poprawki do tego.


Jestem pewien, że wiele osób już natknęło się na problem, w którym iOS 7 ma tendencję do desaturacji koloru paska UINavigationBar to jest przezroczyste.

Moim celem jest osiągnięcie UINavigationBar z tym odcieniem, ale półprzezroczystym:

UINavigationBar, Nieprzezroczysty

[5]}jednak, z przezroczystością, dostaję to. Widok tła jest biały, co jak rozumiem sprawi, że ten widok będzie nieco lżejszy: {]}

UINavigationBar, Translucent

Czy jest jakiś sposób na uzyskanie oryginalnego koloru przy zachowaniu przezroczystości? Zauważyłem, że Facebook był w stanie uzyskać ich pasek, aby być ich bogaty, niebieski kolor, jak wyświetlane tutaj:

Facebook UINavigationBar, Translucent

Więc wiem, że musi być jakiś sposób. Widoki tła oczywiście robią tutaj różnicę, ale większość ich treści jest również szara / biała. Wydaje się, że niezależnie od tego, jaki kolor paska zastosujesz, nie możesz uzyskać żywych kolorów pod przezroczystością.

Aktualizacja z rozwiązaniem.

Oto rozwiązanie, które wymyśliłem. Wziąłem rozwiązanie aprato , a następnie objąłem niestandardowe UINavigationBar w podklasie UINavigationController. utworzyłem repozytorium, które ma tę implementację wymienioną poniżej, wraz z przykładową aplikacją .
////////////////////////////
// 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
Author: Community, 2013-09-19

16 answers

IOS 7.0.3 UPDATE: Jak widać powyżej 7.0.3 zmienił rzeczy. Zaktualizowałem swój gist. Mam nadzieję, że to po prostu zniknie, gdy ludzie będą ulepszać.

Oryginalna Odpowiedź: Skończyłem z włamaniem łączącym dwie pozostałe odpowiedzi. Jestem subclassing UINavigationBar i dodając warstwę z tyłu z dodatkowym miejscem na pokrycie, jeśli którykolwiek z różnych pasków stanu wysokości są w górę. Warstwa jest dostosowywana w podwidokach układu, a kolor zmienia się za każdym razem, gdy ustawisz barintcolor.

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);
  }
 52
Author: Anthony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-25 22:35:26

Zachowanie tintColor dla barów zmieniło się w systemie iOS 7.0. Nie ma już wpływu na tło paska i zachowuje się zgodnie z opisem właściwości tintColor dodanej do UIView. Aby odcień tła paska, użyj -barintcolor.Możesz użyć poniższego kodu, aby aplikacja działała zarówno z ios6, jak i ios7.

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

IS_IOS7 jest makrem zdefiniowanym w pliku pch w następujący sposób.

#define IS_IOS7 ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0)
 10
Author: Bhavesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-31 05:25:28

Nie wymyśliłem tego rozwiązania, ale wydaje się, że działa dość dobrze. Właśnie dodałem go do viewDidLoad na mojej podklasie UINavigationController.

Źródło: 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];
 9
Author: Jamie Hamick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-19 21:21:24

Jednym ze sposobów low-fi byłoby prawdopodobnie przypięcie UIView, czyli wysokości paska nawigacyjnego do górnej części widoku za paskiem. Ustaw ten widok w tym samym kolorze co pasek nawigacyjny, ale baw się alfą, aż uzyskasz pożądane efekty:

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 behind

Tutaj wpisz opis obrazka

(zmieniono kolor z niższych przykładów na przezroczystość podkreślenia. Przezroczystość / rozmycie jest bardziej zauważalne podczas ruchu.)

Podklasowanie UINavigationBar i umieszczenie tego samego widoku nad tło, ale za wszystkim innym prawdopodobnie osiągnie podobne wyniki, będąc mniej chwiejnym.


Innym rozwiązaniem jakie widziałem jest gra z alfą z UINavigationBar:

self.navigationController.navigationBar.alpha = 0.5f;

Edit: właściwie, po przetestowaniu wydaje się, że to nie zapewnia zamierzonego zachowania (lub żadnego zachowania):

.8 Alfa

Pasek nawigacji z .8 Alfa

Unadjusted alpha

Tutaj wpisz opis obrazka

Oczywiście, będziesz chciał to zrobić tylko na urządzeniach z systemem iOS 7. Więc, dodaj kilka sprawdzania wersji przed zaimplementowaniem któregokolwiek z nich.

 6
Author: Kevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:27

Zamiast tworzyć obiekt UIColor w formacie RGB, Użyj HSB i zwiększ parametr nasycenia. (Podziękowania dla sama Soffesa który opisuje tę metodę tutaj )

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

Uwaga: To rozwiązanie to kompromis i nie działa dobrze w przypadku kolorów o wysokim nasyceniu.

Aby wybrać kolor HSB z projektu, możesz użyć narzędzia ColorSnapper , które pozwala po prostu skopiować Format UICOLOR HSB.

Możesz także użyj kategorii Uicolor (GitHub Link ) z David Keegan , aby zmodyfikować istniejące kolory.

 4
Author: bernhard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-15 18:07:05

Problem został naprawiony przez Apple w nowym wydaniu 7.0.3.

 3
Author: smad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-23 09:36:48

Użyłem rozwiązania @aprato, ale znalazłem kilka narożnych przypadków, w których nowe warstwy z nowych VC (np. UINavigationItemButtonViews, UINavigationItemViews, itd.) zostanie automatycznie wstawiony w miejsce poniżej extraColorLayer (co spowoduje, że elementy tytułu lub przycisku zostaną zmienione przez extraColorLayer i tym samym będą słabsze w kolorze niż normalnie). Więc dostosowałem rozwiązanie @aprato, aby zmusić extraColorLayer do pozostania na pozycji indeksu 1. Na pozycji indeksu 1, extraColorLayer pozostaje tuż nad _UINavigationBarBackground, ale pod wszystkim else.

Oto moja Implementacja klasy:

- (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
}
 1
Author: Mr. T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-24 18:55:52

Poprawiłem Twój kod w moim forku: https://github.com/allenhsu/CRNavigationController

Z moją modyfikacją, kolor wyniku na ekranie (wybrany na białym tle) będzie dokładnie taką samą wartością przekazaną do setBarTintColor. Myślę, że to niesamowite rozwiązanie.

 1
Author: Allen Hsu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-23 06:48:53

Żaden z tych hacków nie jest wymagany :). Simply set:

self.navigationController.navigationBar.translucent = NO;

W systemie iOS 7 domyślna przezroczystość została zachowana.

 0
Author: rishabh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-23 16:41:18

W powiązanej notce możesz łatwo ustawić kolor tekstu tytułowego (z cieniem) za pomocą:

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];
 0
Author: bryguy1300,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-26 21:19:45

Natknąłem się na to pytanie podczas próby ustawienia jednolicie kolorowego paska nawigacyjnego z wyłączoną przezroczystością na iOS 7.

Po kilku eksperymentach z barintcolor zorientowałem się, że bardzo łatwym sposobem na posiadanie nieprzezroczystego paska nawigacyjnego jest wykonanie pojedynczego piksela obrazu o pożądanym kolorze, zrobienie z niego rozciągliwego obrazu i ustawienie go na tle paska nawigacyjnego.

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

Trzy linie kodu, bardzo proste i działa zarówno na iOS 6 jak i iOS 7 (barintcolor nie jest obsługiwany w systemie iOS 6).

 0
Author: bizz84,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-11 15:34:04

Istnieje świetny zamiennik kontrolera Dropin uinavigationcontroller dostępny na stoisku Simona dostępny na GitHub tutaj GitHub - C360navigationbar

Jeśli obsługujesz iOS6 wstecz, sprawdź kontroler widoku głównego jako taki:

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;
 0
Author: DoctorG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-23 18:42:15

Jak wspomniano powyżej @bernhard możliwe jest Nasycenie koloru paska, aby uzyskać pożądany wygląd paska nawigacyjnego.

Napisałem Narzędzie BarTintColorOptimizer do tego rodzaju regulacji. Optymalizuje przezroczysty kolor barów, aby rzeczywisty kolor paska pasował do pożądanego koloru w systemie iOS 7.x i Później. Spójrz na ta odpowiedź Po szczegóły.

 0
Author: IvanRublev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:38

Szczerze mówiąc, powyższe odpowiedzi mogą być słuszne, ale podążanie za sztuczką działało dla mnie z łatwością.

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

Oto obrazy używane dla self.imageRed i self.imageBlack.

> czarny obrazek jest w tym nawiasie nie będzie widoczny ponieważ jest przezroczysty:)

> w nawiasach znajduje się czerwony obrazek.

 -1
Author: Sagar R. Kothari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-07 15:44:39

Czy istnieje sposób na użycie @aprato solution bez podklasowania UINavigationBar.

W moim projekcie moim głównym widokiem jest kontroler UIViewController.

Problem polega na tym, że navigationController jest właściwością readonly, czy istnieje sposób użycia klasy you W moim projekcie, ponieważ nie mogę użyć: [[UINavigationController alloc] initWithNavigationBarClass:

Thanks

 -1
Author: amau96,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-12 09:07:09

Łatwym sposobem na uzyskanie pożądanego koloru jest użycie

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

Tak długo, jak Twój obraz ma Alfę, przezroczystość będzie działać i możesz ustawić Alfę, zmieniając obraz. Zostało to właśnie dodane w iOS7. Szerokość i wysokość obrazu wynoszą 640x88px dla pionu (dodaj 20 do 88, jeśli chcesz, aby znajdował się pod paskiem stanu).

 -2
Author: Carter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-20 23:46:37