Mencapai warna-warna cerah dan jelas untuk UINavigationBar yang tembus iOS 7

172

iOS 7.1 UPDATE : Sepertinya solusi untuk memodifikasi saluran alpha di UINavigationBar telah diabaikan dalam pembaruan ini. Saat ini, solusi terbaik tampaknya hanya dengan 'menghadapinya' dan berharap warna apa pun yang Anda pilih dapat memberikan efek tembus cahaya. Saya masih mencari cara untuk mengatasi ini.


iOS 7.0.3 PEMBARUAN : Perpustakaan GitHub yang kami buat telah diperbarui untuk sedikit mengatasi masalah ini ketika menggunakan iOS 7.0.3. Sayangnya, tidak ada formula ajaib untuk mendukung kedua warna yang dibuat di iOS 7.0.2 dan sebelumnya dan iOS 7.0.3. Sepertinya Apple meningkatkan saturasi, tetapi dengan biaya opacity (karena kekaburan kabur tergantung pada level opacity). Saya, bersama dengan beberapa orang lain, sedang berupaya menciptakan perbaikan yang jauh lebih baik untuk ini.


Saya yakin banyak orang telah menemukan masalah di mana iOS 7 cenderung menghilangkan sifat warna UINavigationBar yang tembus cahaya.

Tujuan saya adalah untuk mencapai UINavigationBar dengan warna warna ini, tetapi tembus:

UINavigationBar, Buram

Namun, dengan transparansi, saya mendapatkan ini. Tampilan latar belakang berwarna putih, yang saya mengerti akan membuat tampilan ini sedikit lebih ringan:

UINavigationBar, Tembus

Apakah ada cara untuk mencapai warna asli sambil tetap tembus cahaya? Saya perhatikan Facebook telah bisa menjadikan bar mereka kaya, warna biru, seperti yang ditampilkan di sini:

Facebook UINavigationBar, Translucent

..so saya tahu harus ada cara. Tampilan latar belakang jelas membuat perbedaan di sini, tetapi sebagian besar konten mereka juga abu-abu / putih. Tampaknya terlepas dari warna bar apa pun yang Anda masukkan, Anda tidak dapat mendapatkan warna yang jelas di bawah transparansi.

Diperbarui dengan solusi.

Inilah solusi yang akhirnya saya dapatkan. Saya mengambil solusi aprato dan kemudian memasukkan custom ke UINavigationBardalam UINavigationControllersubclass. Saya telah membuat repositori yang penerapannya tercantum di bawah ini, bersama dengan contoh aplikasi .

////////////////////////////
// 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
SpacePyro
sumber
bukankah Facebook iOS7 UINAvigationBarburam?
Vinzzz
Tidak, ini adalah transparansi yang jauh lebih halus daripada iOS default. Jauh lebih baik, IMO.
Kevin
Navigasi FacebookBar tidak transparan
LE SANG
7
Jelas tembus; silakan lihat tanggapan saya yang diedit.
SpacePyro
2
@Odelya - Ini bukan solusi untuk mendapatkan warna yang benar, tetapi lebih merupakan solusi untuk mengoreksi cahaya yang UINavigationBarsebaik mungkin ketika terkena transparansi di iOS 7.
SpacePyro

Jawaban:

52

iOS 7.0.3 UPDATE: Seperti yang Anda lihat di atas 7.0.3 mengubah hal-hal. Saya telah memperbarui inti saya. Semoga ini akan hilang begitu saja saat orang meningkatkan.

Jawaban Asli: Saya berakhir dengan retasan yang menggabungkan dua jawaban lainnya. Saya subclassing UINavigationBar dan menambahkan lapisan ke belakang dengan beberapa ruang tambahan untuk menutupi jika salah satu dari berbagai bar status ketinggian naik. Lapisan akan disesuaikan dalam tampilan tampilan tata letak dan warna berubah setiap kali Anda mengatur barTintColor.

Intisari: 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);
  }
Anthony
sumber
Di mana Anda menerapkan ini pada ViewController? Di bawah viewDidLoad?
Jeremy
Ini bekerja dengan indah! Saya memutuskan untuk menambahkan ini ke UINavigationControllersubkelas saya . Berikut adalah intinya bagi mereka yang tertarik untuk memiliki kebiasaan UINavigationBardalam UINavigationController.
SpacePyro
@Jeremy seperti SpacePyro Saya memiliki subkelas kontroler nav (yang seperti bilah yang saya gunakan pra 7 untuk penargetan UIAppearance) yang menimpa initWithRootViewControlleruntuk menggunakan ini. Saya telah memperbarui inti saya
Anthony
Um ... oke..aku pikir saya perlu melihat ini di seluruh proyek uji untuk sepenuhnya melihat apa yang Anda maksud. Saya bisa meniru contoh timeuser di bawah ini tapi saya masih sedikit hijau dengan yang ini.
Jeremy
1
@ Tn. Terima kasih! Ketika saya menulisnya belum mendorong :) Tapi saya telah memperbaruinya sekarang, menambahkan UIAppearance untuk opacity dan dukungan untuk NSCoding
Anthony
10

Perilaku tintColor untuk bar telah berubah di iOS 7.0. Tidak lagi memengaruhi latar belakang bilah dan berperilaku seperti yang dijelaskan untuk properti tintColor yang ditambahkan ke UIView. Untuk mewarnai latar belakang bilah, gunakan -barTintColor. Anda dapat menggunakan kode berikut untuk membuat aplikasi berfungsi dengan ios6 dan ios7.

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

IS_IOS7 adalah makro yang didefinisikan dalam file pch sebagai berikut.

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

Saya tidak datang dengan solusi ini tetapi tampaknya bekerja dengan cukup baik. Saya baru saja menambahkannya ke viewDidLoad pada subkelas UINavigationController saya.

Sumber: 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];
Jamie Hamick
sumber
1
Sepertinya setelah mendorong Pengontrol Tampilan baru ke pengontrol Navigasi, setiap item tombol bilah dipindahkan ke bawah lapisan transparansi ini.
Evan Davis
Judul juga dikaburkan oleh lapisan transparansi ini.
Nick Locking
Saya menulis intisari ini. Komentarnya benar; salah satu item tombol ditekan di bawah ketika pengontrol tampilan baru didorong, atau sublayer mewarisi alfa colourView. Saya bercabang jawaban lain dan memperbaiki beberapa hal menjadi drop-in kelas baru: github.com/alanzeino/AZColoredNavigationBar
Alan
Saya dapat menempatkan teks putih dengan memilih gaya Translucent Black Navigation Bar ... ini berhasil bagi saya. Juga atur yourBar.tintColor = [UIColor whiteColor]; untuk tombol khusus lainnya di atas.
Juan Zamora
6

Salah satu cara rendah fi mungkin akan menyematkan UIViewyang adalah ketinggian Bar Navigasi ke bagian atas tampilan di belakang bar. Buat tampilan itu dengan warna yang sama dengan bilah navigasi tetapi mainkan dengan alpha sampai Anda mendapatkan efek yang diinginkan:

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 di belakang

masukkan deskripsi gambar di sini

(Berubah warna dari contoh yang lebih rendah ke penekanan transparansi. Transparansi / kabur lebih terlihat ketika bergerak.)

Subklasifikasi UINavigationBardan menempatkan tampilan yang sama di atas latar belakang, tetapi di balik semua yang lain mungkin akan mencapai hasil yang sama sambil kurang hacky.


Solusi lain yang pernah saya lihat adalah bermain dengan alpha dari UINavigationBar:

self.navigationController.navigationBar.alpha = 0.5f;

Sunting: Sebenarnya, setelah pengujian sepertinya ini tidak memberikan perilaku niat (atau perilaku apa pun):

.8 alpha

Bilah navigasi dengan .8 alpha

Alfa tidak disesuaikan

masukkan deskripsi gambar di sini

Jelas, Anda hanya ingin melakukan ini di perangkat iOS 7. Jadi, tambahkan beberapa versi cek sebelum Anda menerapkan semua ini.

Kevin
sumber
Saya kedua pendekatan memperbarui alpha dan tintColor untuk mendapatkan warna yang Anda cari.
StuartM
Jika Anda bisa mendapatkan efek yang diinginkan dengan cara yang kurang invasif, maka total. Tapi saya tidak yakin seberapa efektif itu.
Kevin
Satu-satunya masalah yang saya dapatkan dengan ini (dan tampaknya tidak terwakili dalam gambar Anda) adalah bahwa itu menambahkan tampilan langsung di atas bilah navigasi, dan sebagai hasilnya, itu menyebabkan kontrol diblokir: cl.ly / image / 3d3C2o0N283S
SpacePyro
Ups, sekarang saya mengerti. Seharusnya[self.navigationController.view insertSubview:backgroundView belowSubview:self.navigationController.navigationBar];
Kevin
Ya, saya pikir itu yang Anda maksud. ;) Ini jelas memberi saya rentang warna yang lebih baik untuk dipilih. Mendapatkan getaran warna asli mungkin tidak akan mungkin mengingat efek blur masih benar-benar membuat desaturasi apa pun di bawahnya. Saya hanya harus hidup dengan warna yang lebih gelap untuk saat ini.
SpacePyro
4

Alih-alih membuat objek UIColor Anda dalam format RGB , gunakan HSB dan tambah parameter saturasi. (Kredit untuk Sam Soffes yang menjelaskan metode ini di sini )

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

Catatan: Solusi ini merupakan tradeoff dan tidak berfungsi dengan baik untuk warna dengan saturasi tinggi.

Untuk memilih warna HSB dari desain Anda, Anda dapat menggunakan alat seperti ColorSnapper yang memungkinkan Anda untuk cukup menyalin format UIColor HSB.

Anda juga dapat mencoba Kategori UIColor ( GitHub Link ) dari David Keegan untuk memodifikasi warna yang ada.

bernhard
sumber
3

Masalahnya sekarang telah diperbaiki oleh Apple dalam rilis 7.0.3 yang baru.

smad
sumber
1
Ya, implementasi warna tint mereka jelas telah berubah di 7.0.3. Saya sekarang dapat mencapai warna yang saya inginkan dengan hanya meningkatkan saturasi sekitar 10-15%. Sebelumnya saya juga perlu memasang lapisan ekstra.
Matej Bukovinski
Terima kasih telah memberi tahu saya! Saya akan mendorong pembaruan ke perpustakaan saya untuk ini.
SpacePyro
1
Dan tidak diperbaiki dalam 7,1> _ <
Leo Natan
1

Saya menggunakan solusi @ aprato tetapi menemukan beberapa kasus sudut di mana layer baru dari VC baru (mis. UINavigationItemButtonViews,, UINavigationItemViewsDll) akan secara otomatis dimasukkan ke posisi di bawah extraColorLayer(yang akan menyebabkan elemen-elemen judul atau tombol dipengaruhi oleh extraColorLayerdan dengan demikian warnanya lebih redup daripada biasanya). Jadi saya menyesuaikan solusi @ aprato untuk memaksa extraColorLayeragar tetap di posisi indeks 1. Di posisi indeks 1, extraColorLayertetap tepat di atas _UINavigationBarBackground, tetapi di bawah segalanya.

Inilah implementasi kelas saya:

- (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
}
Tuan T
sumber
Karena layer dan subview tidak tercampur, saya tidak perlu menambahkan addSubView
Rob van der Veer
1

Saya telah meningkatkan kode Anda di garpu: https://github.com/allenhsu/CRNavigationController

Dengan modifikasi saya, warna hasil di layar (dipilih pada latar belakang putih) akan menjadi nilai yang persis sama setBarTintColor. Saya pikir ini solusi luar biasa.

Allen Hsu
sumber
@JordanBrown tidak diuji pada 7,1 & 8
Allen Hsu
0

Tidak satu pun dari peretasan ini diperlukan :). Cukup atur:

self.navigationController.navigationBar.translucent = NO;

Untuk iOS 7, translucency default telah disimpan ke TRUE.

rishabh
sumber
17
Tetapi pertanyaannya juga membutuhkan transparansi.
Leo Natan
:) Terima kasih, itu berhasil untuk saya. Namun ada batas bawah hitam 1px di bawah nav bar. Apakah ada cara untuk menghapusnya?
Pritesh Desai
0

Pada catatan terkait, Anda dapat mengatur warna teks judul Anda (dengan bayangan) dengan mudah melalui:

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];
bryguy1300
sumber
1
Jika Anda mencoba mencocokkan gaya iOS 7, menggunakan drop shadow pada teks judul Anda mungkin tidak pantas.
Nick Locking
Anda benar, di iOS 7 Apple tidak lagi mengatur bayangan pada teks navbar mereka. Jika Anda menginginkan tampilan khusus, ini akan memberi Anda opsi.
bryguy1300
0

Saya menemukan T / A ini ketika mencoba mengatur bilah navigasi berwarna seragam dengan transparansi DISABLED di iOS 7.

Setelah bereksperimen sebentar dengan barTintColor, saya menemukan bahwa cara yang sangat mudah untuk memiliki bilah navigasi buram adalah dengan membuat gambar piksel tunggal dari warna yang diinginkan, membuat gambar yang dapat direnggangkan darinya, dan mengaturnya ke latar belakangGambar dari bilah navigasi .

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

Tiga baris kode, sangat sederhana dan berfungsi KEDUA di iOS 6 dan iOS 7 (barTintColor tidak didukung di iOS 6).

bizz84
sumber
0

Ada pengganti Dropin UINavigationController yang tersedia dari Simon Booth yang tersedia di GitHub Here GitHub - C360NavigationBar

Jika Anda mendukung iOS6 mundur lakukan pengecekan pada pengendali tampilan root seperti:

PatientListTableViewController * frontViewController = [[Alokasi 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;
DoctorG
sumber
Kecuali saya melewatkan sesuatu, bilah perpustakaan ini tidak tembus cahaya.
Rivera
0

Seperti @bernhard yang disebutkan di atas , dimungkinkan untuk memenuhi warna warna bar untuk mendapatkan tampilan bar navigasi yang diinginkan.

Saya menulis utilitas BarTintColorOptimizer untuk penyesuaian semacam itu. Ini mengoptimalkan warna warna batang transparan untuk membuat warna aktual bilah cocok dengan warna yang diinginkan di iOS 7.x dan yang lebih baru. Lihat jawaban ini untuk detailnya.

IvanRublev
sumber
-1

Terus terang, jawaban di atas mungkin benar tetapi trik berikut ini berhasil untuk saya dengan sangat mudah.

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

Berikut adalah gambar yang digunakan untuk self.imageReddan self.imageBlack.

< self.imageBlack> gambar hitam ada di dalam kurung ini tidak akan terlihat karena transparan :)

< self.imageRed> gambar merah ada di dalam kurung ini.

Sagar R. Kothari
sumber
Ini tidak memberi Anda kabur.
Ortwin Gentz
-1

apakah ada cara untuk menggunakan solusi @aprato tanpa subclassing UINavigationBar.

Dalam proyek saya, tampilan utama saya adalah UIViewController.

masalahnya adalah navigationController adalah properti readonly, apakah ada cara untuk menggunakan kelas Anda dengan proyek saya karena saya tidak dapat menggunakan: [[UINavigationController alloc] initWithNavigationBarClass:

Terima kasih

amau96
sumber
Tidak bisakah Anda membungkus UIViewControllerbagian dalam Anda UINavigationControllerdengan [[[UINavigationController alloc] initWithRootViewController:<YourViewController>]? Ini mungkin lebih baik dijawab sebagai pertanyaan terpisah, daripada posting di sini.
SpacePyro
-2

Cara mudah untuk mendapatkan warna yang Anda inginkan adalah menggunakan

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

Selama gambar Anda memiliki alfa, transparansi akan bekerja dan Anda dapat mengatur alfa dengan mengubah gambar. Ini baru saja ditambahkan di iOS7. Lebar dan tinggi untuk gambar adalah 640x88px untuk vertikal (tambahkan 20 ke 88 jika Anda ingin berada di bawah bilah status).

Tukang gerobak
sumber
Namun ini tidak mempertahankan blur. Ada transparansi, tetapi tidak kabur.
Leo Natan