不少App首頁要作成相似天貓和京東的導航欄,實如今頁面滑動過程當中導航欄漸變的效果。筆者以前在項目裏用過一個三方,後來更新版本失效了,因而決定結合本身對導航欄的認識來實現一下這個功能。完成一個簡易的iOS導航欄顏色漸變方案。git
【文末附運行效果及demo】github
PS:現有版本對代碼進行了重構,經過新增category並利用runtime的method swizzling實現兩行代碼輕鬆搞定。詳情參考README。bash
//方法一
self.navigationController.navigationBar.backgroundColor = [UIColor redColor];
//方法二
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"red.png"] forBarMetrics:UIBarMetricsDefault];
複製代碼
以上兩個方法均可覺得導航欄添加顏色,可是方法一的效果並不是此處所需。app
緣由在於 UINavigationBar
的結構中添加了 UIView
、 UIImageView
、 UILabel
等控件,覆蓋了 UINavigationBar
。ui
方法二的效果符合預期。spa
直接貼代碼並附上註釋:3d
- (UIImage *)imageWithColor:(UIColor *)color {
//建立1像素區域並開始繪圖
CGRect rect = CGRectMake(0, 0, 1, 1);
UIGraphicsBeginImageContext(rect.size);
//建立畫板並填充顏色和區域
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
//從畫板上獲取圖片並關閉圖片繪圖
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
複製代碼
一般展現信息頁面都存放於滑動視圖(UIScrollView
、UITableView
、UICollectionView
等),這就不難想到能夠在滑動視圖的 scrollViewDidScroll:
這個方法里根據滑動視圖縱向偏移量來計算顏色的透明度的。code
除了以上的問題思考和基本原理,實際實現過程當中還有一些須要注意的內容。cdn
當頁面下拉時隱藏導航欄,方法有兩個:blog
//方法一:
[self.navigationController setNavigationBarHidden:YES];
//方法二:
self.navigationController.navigationBar.hidden = YES;
複製代碼
以上兩個方法效果相同,區別在於一個是操做 navigationController
的屬性(navigationBar
是 navigationController
的一個屬性),一個是操做navigationBar
的屬性。
可是,方法一會出現一個bug,就是當頁面初始狀態時 setNavigationBarHidden
爲 YES
,也就至關於 navigationBar
那一刻是不存在的,那麼導航欄上的控件也就天然看不到,並且 navigationBar
的出現和消失會很突兀。
採用方法二效果會好不少,由於navigationBar
自己是存在的,只是作了顯示和隱藏的操做,過渡也相對順滑。
導航欄做爲的公共區域,咱們能夠對它進行自定義,同時也要考慮當前頁面的導航欄和其餘頁面導航欄之間的相互影響。
shadowImage
,在 viewWillAppear
對其隱藏,又在 viewWillDisappear
對其作了還原。scrollViewDidScroll:
方法來計算當前應該呈現的顏色。爲了方便使用,封裝一個 UINavigationBar
的category: UINavigationBar+ChangeColor。
//UINavigationBar+ChangeColor.m文件
//核心方法
- (void)changeColor:(UIColor *)color withOffsetY:(CGFloat)offsetY {
if (offsetY < 0) {
// 下拉時導航欄隱藏
self.hidden = YES;
}else {
self.hidden = NO;
// 計算透明度,180爲隨意設置的偏移量臨界值
CGFloat alpha = offsetY / 180 > 1.0f ? 1 : (offsetY / 180);
// 設置一個顏色並轉化爲圖片
UIImage *image = [self imageWithColor:[color colorWithAlphaComponent:alpha]];
[self setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
self.translucent = alpha >= 1.0f ? NO : YES;
}
}
複製代碼
使用方法:
star
:隱藏導航欄下的橫線,將背景色置空,通常在viewWillAppear
中調用,;changeColor:WithScrollView:AndValue:
:傳入顏色、滑動視圖、臨界值來實現,通常在 scrollViewDidScroll
中調用;reset
:顯示導航欄下橫線,還原導航欄,通常在 viewWillDisappear
中調用。//VC.m文件
/* 頁面即將顯示 */
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar start];
//該頁面呈現時手動調用計算導航欄此時應當顯示的顏色
[self scrollViewDidScroll:_tableview];
}
/* 頁面即將消失 */
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController.navigationBar reset];
}
/* 滑動過程當中作處理 */
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self.navigationController.navigationBar changeColor:[UIColor redColor] withOffsetY:scrollView.contentOffset.y];
}
複製代碼