1. 程式人生 > >iOS漸變導航欄封裝

iOS漸變導航欄封裝

uifont LEDE nonatomic 偏移量 為我 info 簡單 返回 fse

由於最近開發的幾個項目都有漸變導航欄,每次寫的時候都要copy一堆關於導航漸變相關的代碼,顯得類很冗余,所以花了點時間封裝了一個漸變類,直接繼承就可以滿足大部分需求啦,這裏簡單寫一下心路歷程:

漸變的核心幾個部分:

1.狀態欄的變色:

添加一個狀態欄屬性BooL變量

@property(nonatomic,assign)BOOL lightStatusBar;//狀態欄的顏色控制

我們可以在ViewController裏面重寫系統的這個方法來動態設置狀態欄顏色(白色/黑色):
-(UIStatusBarStyle)preferredStatusBarStyle{
return self.lightStatusBar ? UIStatusBarStyleLightContent : UIStatusBarStyleDefault;
}
如果需要主動的觸發上面的方法改變狀態欄顏色,我們可以直接調用這個方法 [self setNeedsStatusBarAppearanceUpdate];在ViewController寫完上面兩步,滑動導航欄會發現好像沒什麽卵用,狀態欄顏色沒變啊!

因為我們需要在UINavigationController裏面重寫下面這個方法-(UIViewController *)childViewControllerForStatusBarStyle;為什麽要重寫這個?這個方法默認返回值是nil,也就是當我們調用setNeedsStatusBarAppearanceUpdate的時候,系統會調用container(容器控制器)的preferredStatusBarStyle這個方法(app.window.rootViewController的preferred的方法,一般我們用UINavigationController或者UITabBarController來做container),也就是根本不會調用子控制器(我們所看到的UIViewcontroller)的preferredStatusBarStyle方法。這個時候- (UIViewController *)childViewControllerForStatusBarStyle:就派上用場了

給UINavigationController添加一個分類添加如下

技術分享圖片

重寫這個方法,系統會調用container(容器控制器)就會返回當前的UIViewController,從而UIViewController裏面重寫的方法就會調用,狀態欄的顏色就會相應改變。以上就是狀態欄的變色出處理

2.導航欄的漸變

先做一下基礎的設置:

1.禁止系統對繼承Scrollview的控件的自動偏移技術分享圖片

2.隱藏導航欄底部的線條,不處理的話導航欄透明時會明顯看到一條黑線,辣眼睛。寫個遞歸找到線條

技術分享圖片

調用上面方法找到線條圖片,隱藏即可。

UIImageView *iamgeV = [self findBackLineImageV:self.navigationController.navigationBar];
iamgeV.hidden = YES;

當我們滑動的時候會觸發代理方法(必須要是繼承Scrollview的控件設置代理才會觸發):

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
}

在上面的方法我們主要做以下幾件事情(把上面方法內容拆分說明一下):

1.滑動偏移量獲取,通過滑動偏移量計算導航欄的透明度。

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
offset = scrollView.contentOffset.y;
UIColor *color = [UIColor colorWithWhite:1.0 alpha:offset/self.offsetChange];
[self.navigationController.navigationBar setBackgroundImage:[self imageWithColor:color] forBarMetrics:UIBarMetricsDefault];
}

//繪制一張圖片
- (UIImage *)imageWithColor:(UIColor *)color {
CGSize size = CGSizeMake(1, 1);
if (!color || size.width <= 0 || size.height <= 0) return nil;
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

2.滑動偏移量到設置的偏移量臨界值時的處理(切換back圖片,標題文字顏色,狀態欄的bool值等)。

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{

//導航欄漸變處理
if (offset >= _offsetChange) {
[self setBackNavNomal];
}else{
[self setBackNavDiaphanous];
}
}

//不透明導航欄
-(void)setBackNavNomal
{
self.navigationController.navigationBar.titleTextAttributes=@{NSForegroundColorAttributeName: self.notLucencyTitleColor,NSFontAttributeName:[UIFont systemFontOfSize:18]};
[self setNavigationLeftItemWithImageName:@"more_dark"];
[self.rightBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
self.lightStatusBar = NO;
}

//透明導航欄
-(void)setBackNavDiaphanous
{
self.navigationController.navigationBar.titleTextAttributes= @{NSForegroundColorAttributeName: self.lucencyTitleColor,NSFontAttributeName:[UIFont systemFontOfSize:18]};
[self setNavigationLeftItemWithImageName:@"navigationBack"];
[self.rightBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
self.lightStatusBar = YES;
}

3.當tableview有組頭並且組頭要懸浮在導航欄下面,需要做的處理。

self.contentHeight為tableview的占屏大小,如果contentSize不用滑動就能顯示完整,contentInset就不要修改,不然向上滑會有點bug。

self.offsetChange參數:沒組頭一般默認64就行,有組頭則為組頭到頂部的距離

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{

if (self.tableView.contentSize.height >= self.contentHeight) {
//導航欄漸變處理
if (offset >= self.offsetChange) {
self.tableView.contentInset = UIEdgeInsetsMake(KStatusBarAndNavigationBarHeight, 0, 0, 0);
}else{
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
}

}

}

整體-(void)scrollViewDidScroll:(UIScrollView *)scrollView 方法裏面就是做上面三件事啦

技術分享圖片

做完這些就可以實現漸變了,項目中用的比較多的話直接繼承設置一下參數就可以了。

demon地址:https://github.com/yizhixiafancai/ShadeViewController

iOS漸變導航欄封裝