弄了一年多的微信小程序一罩,終于又回到iOS了廊驼,廢話不多說犹芹,進(jìn)入正題:
&更改導(dǎo)航欄背景顏色
首先來說更改導(dǎo)航欄顏色的方式有很多熙涤,比如自定義一個導(dǎo)航欄阁苞,但是這樣就會破壞掉系統(tǒng)導(dǎo)航欄的功能(比如側(cè)滑返回)而且也失去了系統(tǒng)導(dǎo)航欄的平滑過渡困檩。
相對于自定義,我們也可以更改系統(tǒng)的導(dǎo)航欄顏色那槽,比較簡單的方式是悼沿,直接設(shè)置導(dǎo)航欄的tintColor 如下:
self.navigationController.navigationBar.barTintColor = [UIColor redColor];
這種方法可以很大程度上實(shí)現(xiàn)導(dǎo)航欄顏色渲染,但是美中不足的是骚灸,這樣渲染出來的顏色和實(shí)際顏色會有一丁點(diǎn)的色差糟趾,若果對設(shè)計(jì)的要求不高,這個方法完全可以行得通甚牲。
接下來我們來介紹一個略微麻煩的方式义郑,雖然麻煩,但是為了程序員通有的強(qiáng)迫癥丈钙,這點(diǎn)麻煩還是值得的
其原理很簡單非驮,首先找到導(dǎo)航欄的底視圖,并在該視圖上插入一層我們自定義的視圖(也許有人會問都找到底視圖了著恩,為什么還要插入自己的視圖院尔,直接用底視圖不就得了,這個問題很好回答喉誊,樓主任性)
對于這種麻煩而又常用的東西邀摆,我們首先會想到把他單獨(dú)拿出來寫到一個類里,這里也不例外伍茄,我們先創(chuàng)建一個 UINavigationBar 的分類栋盹,姑且叫做(handle)然后在里面添加一個方法 如下:
#import <UIKit/UIKit.h>
@interface UINavigationBar (handle)
/**
更改導(dǎo)航欄顏色和圖片
@param color 顏色
@param barImage 圖片
*/
- (void)navBarBackGroundColor:(UIColor *_Nullable)color image:(UIImage *_Nullable)barImage;
@end
看到這個方法名,你一定已經(jīng)知道它的作用了敷矫,當(dāng)然光有名字肯定不行例获,那我們就去.m文件里實(shí)現(xiàn)它,首先在.m文件中導(dǎo)入runtime頭文件添加該分類的匿名類別 如下:
#import "UINavigationBar+handle.h"
#import <objc/runtime.h>
@interface UINavigationBar()
@property (nonatomic, strong) UIImage *backClearImage;
@property (nonatomic, strong) UIImage *lineClearImage;
@property (nonatomic, strong) MyNavLayer *myLayer; //自定義插入層曹仗,自定義操作都要在這一層上進(jìn)行
@implementation UINavigationBar (handle)
- (void)navBarBackGroundColor:(UIColor *)color image:(UIImage *)barImage {
...
}
@end
由于是在分類中榨汤,由于分類中無法建立變量,所以所用到的屬性需要runtime 關(guān)聯(lián)一下怎茫,方法去看我的demo
接下來我們來實(shí)現(xiàn)這個更改顏色和背景圖片的方法
1收壕,使用kvc找到navigationbar的底視圖 如下:
UIView *backView = [self valueForKey:@"backgroundView"];
2,因?yàn)槲覀円迦胱约憾x的圖層轨蛤,所以我們要先把原來導(dǎo)航欄的特征去掉(這里不是去掉導(dǎo)航欄蜜宪,而是把其透明處理),方法很簡單祥山,只需要用一個空的image去填充原來的背景 如下:透明化背景圃验,透明化底線
//通過插入空image把背景變透明
if (!self.backClearImage) {
self.backClearImage = [[UIImage alloc]init];
[self setBackgroundImage:self.backClearImage
forBarMetrics:UIBarMetricsDefault];
self.barStyle = UIBarStyleBlackOpaque;
}
//去掉系統(tǒng)底線,使用自定義底線
if (!self.lineClearImage) {
self.lineClearImage = [[UIImage alloc]init];
[self setShadowImage:self.lineClearImage];
}
*題外話:說道這里我們說一下為什么樓主不用原底層視圖缝呕,而是要自定義一個澳窑,首先直接在backView上進(jìn)行更是不行的斧散,該底視圖的屬性是無法更的,比如(backView.backGroundColor = [UIColor redColor] ;)無效照捡,如果還想實(shí)現(xiàn)背景的更改颅湘,就要從這個空image入手,首先準(zhǔn)備一個1x1的帶顏色的圖片(當(dāng)然如果顏色不固定也可以通過drawrect畫一張自定義顏色的視圖然后轉(zhuǎn)成image)然后用該image去填充原來的背景image就可以實(shí)現(xiàn)背景顏色的變換了栗精,大家可能看出來了闯参,這非常的不靈活,所以樓主也不是很任性悲立,對吧鹿寨。
好了,回到正題:
第三步就很簡單了薪夕,前面視圖已經(jīng)找到了脚草,而且也完成了元導(dǎo)航欄的透明處理,接下來我們只需要把自己的視圖的插入到底視圖上就OK了
導(dǎo)航欄的高度 = navigationBar的高度 + 狀態(tài)欄的高度
因?yàn)槭莕avigationBar的分類 所以navigationBar的高度:
CGFloat barHeight = self.bounds.size.height;
狀態(tài)欄高度:
CGFloat statusHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
完整代碼如下(myLayer為自定義導(dǎo)航欄層原献,繼承自calayer):
if (!self.myLayer) {
//狀態(tài)欄高度
CGFloat statusHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
//導(dǎo)航欄高度
CGFloat barHeight = self.bounds.size.height;
CGRect barBounds = self.bounds;
barBounds.size.height = statusHeight + barHeight;
self.myLayer = [[MyNavLayer alloc]initWithFrame:barBounds];
}
if (color) {
self.myLayer.backColor = color;
}
if (barImage) {
self.myLayer.backImage = barImage;
}
//通過kvc找到系統(tǒng)導(dǎo)航欄背景層馏慨,把自定義層添加到背景層
[[[self valueForKey:@"backgroundView"] layer] addSublayer:self.myLayer];
以上便是更改顏色的方法,使用時導(dǎo)入該分類如下:
#import "ViewController.h"
#import "UINavigationBar+handle.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"紅色導(dǎo)航欄";
[self.navigationController.navigationBar navBarBackGroundColor:[UIColor redColor] image:nil];//顏色
}
&更改導(dǎo)航欄透明度
有了上面的鋪墊姑隅,透明應(yīng)該不在話下了写隶,原理和改背景顏色一樣,自定義視圖讲仰,然后更改自定義視圖的透明度
重復(fù)的東西這里就不贅述了慕趴,直接貼出更改方法和實(shí)現(xiàn):
#import <UIKit/UIKit.h>
@interface UINavigationBar (handle)
/**
更改導(dǎo)航欄顏色和圖片
@param color 顏色
@param barImage 圖片
*/
- (void)navBarBackGroundColor:(UIColor *_Nullable)color image:(UIImage *_Nullable)barImage;
/**
更改透明度
@param alpha 導(dǎo)航欄透明度
*/
- (void)navBarAlpha:(CGFloat)alpha;
@end
方法實(shí)現(xiàn):
if (!self.myLayer) {
//狀態(tài)欄高度
CGFloat statusHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
//導(dǎo)航欄高度
CGFloat barHeight = self.bounds.size.height;
CGRect barBounds = self.bounds;
barBounds.size.height = statusHeight + barHeight;
self.myLayer = [[MyNavLayer alloc]initWithFrame:barBounds];
}
self.myLayer.alpha = alpha;
//通過kvc找到系統(tǒng)導(dǎo)航欄背景層,把自定義層添加到背景層
[[[self valueForKey:@"backgroundView"] layer] addSublayer:self.myLayer];
好了鄙陡,到這里就完成了冕房,這里的代碼只是原理,需要的話直接去下載趁矾,然后把分類UINavigationBar+handle放到自己的項(xiàng)目里就OK了
為了換一句辛苦耙册,樓主花了一上午。
https://github.com/Xiexingda/NavBarHandle.git